#!/usr/bin/env python # Copyright (c) Barefoot Networks, Inc. # Licensed under the Apache License, Version 2.0 (the "License") # Compiler from P4 to EBPF # (See http://www.slideshare.net/PLUMgrid/ebpf-and-linux-networking). # This compiler in fact generates a C source file # which can be compiled to EBPF using the LLVM compiler # with the ebpf target. # # Main entry point. import argparse import os import traceback import sys import target from p4_hlir.main import HLIR from ebpfProgram import EbpfProgram from compilationException import * from programSerializer import ProgramSerializer def get_parser(): parser = argparse.ArgumentParser(description='p4toEbpf arguments') parser.add_argument('source', metavar='source', type=str, help='a P4 source file to compile') parser.add_argument('-g', dest='generated', default="router", help="kind of output produced: filter or router") parser.add_argument('-o', dest='output_file', default="output.c", help="generated C file name") return parser def process(input_args): parser = get_parser() args, unparsed_args = parser.parse_known_args(input_args) has_remaining_args = False preprocessor_args = [] for a in unparsed_args: if a[:2] == "-D" or a[:2] == "-I" or a[:2] == "-U": input_args.remove(a) preprocessor_args.append(a) else: has_remaining_args = True # trigger error if has_remaining_args: parser.parse_args(input_args) if args.generated == "router": isRouter = True elif args.generated == "filter": isRouter = False else: print("-g should be one of 'filter' or 'router'") print("*** Compiling ", args.source) return compileP4(args.source, args.output_file, isRouter, preprocessor_args) class CompileResult(object): def __init__(self, kind, error): self.kind = kind self.error = error def __str__(self): if self.kind == "OK": return "Compilation successful" else: return "Compilation failed with error: " + self.error def compileP4(inputFile, gen_file, isRouter, preprocessor_args): h = HLIR(inputFile) for parg in preprocessor_args: h.add_preprocessor_args(parg) if not h.build(): return CompileResult("HLIR", "Error while building HLIR") try: basename = os.path.basename(inputFile) basename = os.path.splitext(basename)[0] config = target.BccConfig() e = EbpfProgram(basename, h, isRouter, config) serializer = ProgramSerializer() e.toC(serializer) f = open(gen_file, 'w') f.write(serializer.toString()) return CompileResult("OK", "") except CompilationException as e: prefix = "" if e.isBug: prefix = "### Compiler bug: " return CompileResult("bug", prefix + e.show()) except NotSupportedException as e: return CompileResult("not supported", e.show()) except: return CompileResult("exception", traceback.format_exc()) # main entry point if __name__ == "__main__": result = process(sys.argv[1:]) if result.kind != "OK": print(str(result))