1# Copyright (c) Barefoot Networks, Inc. 2# Licensed under the Apache License, Version 2.0 (the "License") 3 4from programSerializer import ProgramSerializer 5 6# abstraction for isolating target-specific features 7 8# Base class for representing target-specific configuration 9class TargetConfig(object): 10 def __init__(self, target): 11 self.targetName = target 12 13 def getIncludes(self): 14 return "" 15 16 def serializeLookup(self, serializer, tableName, key, value): 17 serializer.appendFormat("{0} = bpf_map_lookup_elem(&{1}, &{2});", 18 value, tableName, key) 19 20 def serializeUpdate(self, serializer, tableName, key, value): 21 serializer.appendFormat( 22 "bpf_map_update_elem(&{0}, &{1}, &{2}, BPF_ANY);", 23 tableName, key, value) 24 25 def serializeLicense(self, serializer, licenseString): 26 assert isinstance(serializer, ProgramSerializer) 27 serializer.emitIndent() 28 serializer.appendFormat( 29 "char _license[] {0}(\"license\") = \"{1}\";", 30 self.config.section, licenseString) 31 serializer.newline() 32 33 def serializeCodeSection(self, serializer): 34 assert isinstance(serializer, ProgramSerializer) 35 serializer.appendFormat("{0}(\"{1}\")", self.section, self.entrySection) 36 37 def serializeTableDeclaration(self, serializer, tableName, 38 isHash, keyType, valueType, size): 39 assert isinstance(serializer, ProgramSerializer) 40 assert isinstance(tableName, str) 41 assert isinstance(isHash, bool) 42 assert isinstance(keyType, str) 43 assert isinstance(valueType, str) 44 assert isinstance(size, int) 45 46 serializer.emitIndent() 47 serializer.appendFormat("struct {0} {1}(\"maps\") {2} = ", 48 self.tableName, self.section, tableName) 49 serializer.blockStart() 50 51 serializer.emitIndent() 52 serializer.append(".type = ") 53 if isHash: 54 serializer.appendLine("BPF_MAP_TYPE_HASH,") 55 else: 56 serializer.appendLine("BPF_MAP_TYPE_ARRAY,") 57 58 serializer.emitIndent() 59 serializer.appendFormat(".{0} = sizeof(struct {1}), ", 60 self.tableKeyAttribute, keyType) 61 serializer.newline() 62 63 serializer.emitIndent() 64 serializer.appendFormat(".{0} = sizeof(struct {1}), ", 65 self.tableValueAttribute, valueType) 66 serializer.newline() 67 68 serializer.emitIndent() 69 serializer.appendFormat(".{0} = {1}, ", self.tableSizeAttribute, size) 70 serializer.newline() 71 72 serializer.blockEnd(False) 73 serializer.endOfStatement(True) 74 75 def generateDword(self, serializer): 76 serializer.appendFormat( 77 "static inline {0}64 load_dword(void *skb, {0}64 off)", 78 self.uprefix) 79 serializer.newline() 80 serializer.blockStart() 81 serializer.emitIndent() 82 serializer.appendFormat( 83 ("return (({0}64)load_word(skb, off) << 32) | " + 84 "load_word(skb, off + 4);"), 85 self.uprefix) 86 serializer.newline() 87 serializer.blockEnd(True) 88 89 90# Represents a target that is compiled within the kernel 91# source tree samples folder and which attaches to a socket 92class KernelSamplesConfig(TargetConfig): 93 def __init__(self): 94 super(SocketConfig, self).__init__("Socket") 95 self.entrySection = "socket1" 96 self.section = "SEC" 97 self.uprefix = "u" 98 self.iprefix = "i" 99 self.tableKeyAttribute = "key_size" 100 self.tableValueAttribute = "value_size" 101 self.tableSizeAttribute = "max_entries" 102 self.tableName = "bpf_map_def" 103 self.postamble = "" 104 105 def getIncludes(self): 106 return """ 107#include <uapi/linux/bpf.h> 108#include <uapi/linux/if_ether.h> 109#include <uapi/linux/if_packet.h> 110#include <uapi/linux/ip.h> 111#include <linux/skbuff.h> 112#include <linux/netdevice.h> 113#include "bpf_helpers.h" 114""" 115 116 117# Represents a target compiled by bcc that uses the TC 118class BccConfig(TargetConfig): 119 def __init__(self): 120 super(BccConfig, self).__init__("BCC") 121 self.uprefix = "u" 122 self.iprefix = "i" 123 self.postamble = "" 124 125 def serializeTableDeclaration(self, serializer, tableName, 126 isHash, keyType, valueType, size): 127 assert isinstance(serializer, ProgramSerializer) 128 assert isinstance(tableName, str) 129 assert isinstance(isHash, bool) 130 assert isinstance(keyType, str) 131 assert isinstance(valueType, str) 132 assert isinstance(size, int) 133 134 serializer.emitIndent() 135 if isHash: 136 kind = "hash" 137 else: 138 kind = "array" 139 serializer.appendFormat( 140 "BPF_TABLE(\"{0}\", {1}, {2}, {3}, {4});", 141 kind, keyType, valueType, tableName, size) 142 serializer.newline() 143 144 def serializeLookup(self, serializer, tableName, key, value): 145 serializer.appendFormat("{0} = {1}.lookup(&{2});", 146 value, tableName, key) 147 148 def serializeUpdate(self, serializer, tableName, key, value): 149 serializer.appendFormat("{0}.update(&{1}, &{2});", 150 tableName, key, value) 151 152 def generateDword(self, serializer): 153 pass 154 155 def serializeCodeSection(self, serializer): 156 pass 157 158 def getIncludes(self): 159 return """ 160#include <uapi/linux/bpf.h> 161#include <uapi/linux/if_ether.h> 162#include <uapi/linux/if_packet.h> 163#include <uapi/linux/ip.h> 164#include <linux/skbuff.h> 165#include <linux/netdevice.h> 166#include <linux/pkt_cls.h> 167""" 168 169 def serializeLicense(self, serializer, licenseString): 170 assert isinstance(serializer, ProgramSerializer) 171 pass 172