def buildPacketOut(self, payload, metadata=None): packet_out = p4runtime_pb2.PacketOut() packet_out.payload = payload if metadata: packet_out.metadata.extend([ self.get_metadata_pb(metadata_id, value) for metadata_id, value in metadata.iteritems() ]) return packet_out
def verify_packet_out(self, pkt, out_port): port_hex = stringify(out_port, 2) packet_out = p4runtime_pb2.PacketOut() packet_out.payload = str(pkt) egress_physical_port = packet_out.metadata.add() egress_physical_port.metadata_id = 1 egress_physical_port.value = port_hex self.send_packet_out(packet_out) testutils.verify_packet(self, pkt, out_port)
def build_packet_out(self, payload, metadata=None): packet_out = p4runtime_pb2.PacketOut() packet_out.payload = payload if not metadata: return packet_out for name, value in metadata.items(): p4info_meta = self.get_packet_metadata("packet_out", name) meta = packet_out.metadata.add() meta.metadata_id = p4info_meta.id meta.value = encode(value, p4info_meta.bitwidth) return packet_out
def sendPacketOutRaw(self, pkt): sleep(self.controlPlaneDelay) #print "sending packetout to switch %s" % self.name packet_out_req = p4runtime_pb2.PacketOut() packet_out_req.payload = pkt req = p4runtime_pb2.StreamMessageRequest() req.packet.CopyFrom(packet_out_req) #print "sending packet %s to switch %s" % (req.packet.payload.encode('hex'), self.name) self.stream_out_q.put(req)
def sendPacketOutLabel(self, payload, flowID): sleep(self.controlPlaneDelay) #print "sending packetout to switch %s" % self.name flowIDbyte = ('%%0%dx' % (4 << 1) % flowID).decode('hex')[-4:] #flowIDbyte += bytearray(flowID) packet_out_req = p4runtime_pb2.PacketOut() packet_out_req.payload = bytes('\24\063') + bytes(flowIDbyte) + bytes( payload) req = p4runtime_pb2.StreamMessageRequest() req.packet.CopyFrom(packet_out_req) self.stream_out_q.put(req)
def buildMetadataBasedPacketOut(self, clabFlag, linkID, bitmask, level_to_link_id_store_index , port = 255): ''' port_num_t egress_port; bit<7> _pad; //Previous all fields are not necessary for CLB. TODO at sometime we will trey to clean up them. But at this moment we are not focusing on that bit<8> clb_flags; //Here we will keep various falgs for CLB //--------bit-7--------|| If this bit is set then reet the counter //--------bit-6--------|| If this bit is set then this is a port delete packet //--------bit-5--------|| If this bit is set then this is a port insert packet //--------bit-4--------|| Other bits are ununsed at this moment //--------bit-3--------|| //--------bit-2--------|| //--------bit-1--------|| //--------bit-0--------|| bit<32> link_id; bit<32> bitmask; //Here we are keeping all 32 bit to avoid compile time configuration complexity. At apply blo0ck we will slice necesssary bits. bit<32> level_to_link_id_store_index; // ''' rawPktContent = (255).to_bytes(2,'big') # first 2 byte egressport and padding rawPktContent = rawPktContent + (clabFlag).to_bytes(1,'big') rawPktContent = rawPktContent + (linkID).to_bytes(4,'big') rawPktContent = rawPktContent + (bitmask).to_bytes(4,'big') rawPktContent = rawPktContent + (level_to_link_id_store_index).to_bytes(4,'big') packet_out_req = p4runtime_pb2.StreamMessageRequest() port_hex = port.to_bytes(length=2, byteorder="big") packet_out = p4runtime_pb2.PacketOut() egress_physical_port = packet_out.metadata.add() egress_physical_port.metadata_id = 1 egress_physical_port.value = port_hex clb_flag_metadata_field = packet_out.metadata.add() clb_flag_metadata_field.metadata_id = 3 clb_flag_metadata_field.value = (clabFlag).to_bytes(1,'big') linkID_metadata_field = packet_out.metadata.add() linkID_metadata_field.metadata_id = 4 linkID_metadata_field.value = (linkID).to_bytes(4,'big') bitmask_metadata_field = packet_out.metadata.add() bitmask_metadata_field.metadata_id = 5 bitmask_metadata_field.value = (bitmask).to_bytes(4,'big') level_to_link_id_store_index_metadata_field = packet_out.metadata.add() level_to_link_id_store_index_metadata_field.metadata_id = 6 level_to_link_id_store_index_metadata_field.value = (level_to_link_id_store_index).to_bytes(4,'big') packet_out.payload = rawPktContent packet_out_req.packet.CopyFrom(packet_out) return packet_out_req
def send_packet_out(self, pkt, port): packet_out_req = p4runtime_pb2.StreamMessageRequest() port_hex = stringify(port, 2) packet_out = p4runtime_pb2.PacketOut() packet_out.payload = str(pkt) egress_physical_port = packet_out.metadata.add() egress_physical_port.metadata_id = 1 egress_physical_port.value = port_hex packet_out_req.packet.CopyFrom(packet_out) self.stream_out_q.put(packet_out_req)
def runPacketOutTest(self, pkt): for port in [self.port1, self.port2]: port_hex = stringify(port, 2) packet_out = p4runtime_pb2.PacketOut() packet_out.payload = str(pkt) egress_physical_port = packet_out.metadata.add() egress_physical_port.metadata_id = 1 egress_physical_port.value = port_hex self.send_packet_out(packet_out) testutils.verify_packet(self, pkt, port) testutils.verify_no_other_packets(self)
def sendDiscpkt(s, port): pkt = dpkt.ethernet.Ethernet() pkt.src = '\377\377\377\377\377\377' pkt.dst = '\377\377\377\377\377\377' pkt.type = 0xffff pkt.data = '\000' + str(unichr(port)) + s.name packet_out_req = p4runtime_pb2.PacketOut() # send a disc packet to the destination packet_out_req.payload = bytes(pkt) req = p4runtime_pb2.StreamMessageRequest() req.packet.CopyFrom(packet_out_req) s.stream_out_q.put(req)
def send_packet_out(self, pkt, port, clnt): self.packetOutLock.acquire(blocking=True) packet_out_req = p4runtime_pb2.StreamMessageRequest() # port_hex = stringify(port, 2) port_hex = port.to_bytes(length=2, byteorder="big") packet_out = p4runtime_pb2.PacketOut() packet_out.payload = pkt.encode() egress_physical_port = packet_out.metadata.add() egress_physical_port.metadata_id = 1 egress_physical_port.value = port_hex packet_out_req.packet.CopyFrom(packet_out) clnt.stream_out_q.put(packet_out_req) self.packetOutLock.release()
def run(self): for i in range(1, 6): packet_out = p4runtime_pb2.PacketOut() packet_out.payload = self.generate_lldp_packet(i) # del packet_out.metadata[:] # p4runtime_metadata1 = p4runtime_pb2.PacketMetadata() # p4runtime_metadata1.metadata_id = 1 # p4runtime_metadata1.value = struct.pack(">H", i) # packet_out.metadata.append(p4runtime_metadata1) # p4runtime_metadata2 = p4runtime_pb2.PacketMetadata() # p4runtime_metadata2.metadata_id = 2 # p4runtime_metadata2.value = struct.pack(">H", 5) # packet_out.metadata.append(p4runtime_metadata2) self.sw.PacketOut(packet_out) print 'receive'
def build_packet_out(self, pkt, port, do_forwarding=False): packet_out = p4runtime_pb2.PacketOut() packet_out.payload = bytes(pkt) # egress_port port_md = packet_out.metadata.add() port_md.metadata_id = 1 port_md.value = stringify(port, 2) # do_forwarding do_forwarding_md = packet_out.metadata.add() do_forwarding_md.metadata_id = 2 do_forwarding_md.value = stringify(1 if do_forwarding else 0, 1) # pad pad_md = packet_out.metadata.add() pad_md.metadata_id = 3 pad_md.value = stringify(0, 1) return packet_out
def encode_packet_out_metadata(self, pktout_dict): ret = p4runtime_pb2.PacketOut() ret.payload = pktout_dict['payload'] pktout_info = self.controller_packet_metadata_dict_key_name( "packet_out") for k, v in pktout_dict['metadata'].items(): md = ret.metadata.add() md.metadata_id = pktout_info[k]['id'] # I am not sure, but it seems that perhaps some code after # this point expects the bytes array of the values of the # controller metadata fields to be the full width of the # field, not the abbreviated version that omits leading 0 # bytes that most P4Runtime API messages expect. bitwidth = pktout_info[k]['bitwidth'] bytewidth = (bitwidth + 7) // 8 #logging.debug("dbg encode k=%s v=%s bitwidth=%s bytewidth=%s" # "" % (k, v, bitwidth, bytewidth)) md.value = stringify(v, bytewidth) return ret
def buildMetadataBasedPacketOut(self, isDelete, rank, port, rankMinIndex, rankMaxIndex, newPortIndex, bitmask, packet_out_port=255): ''' port_num_t egress_port; bit<7> _pad; //Previous all fields are not necessary for CLB. TODO at sometime we will trey to clean up them. But at this moment we are not focusing on that bit<8> top_k_path_flags; //Here we will keep various falgs for CLB //--------bit-7--------|| If this bit is set then reet the counter //--------bit-6--------|| If this bit is set then this is a port delete packet //--------bit-5--------|| If this bit is set then this is a port insert packet //--------bit-4--------|| Other bits are ununsed at this moment //--------bit-3--------|| //--------bit-2--------|| //--------bit-1--------|| //--------bit-0--------|| bit<K> bitmask; bit<32> rank; bit<32> port; bit<32> rank_max_index; bit<32> rank_min_index; bit<32> new_port_index; ''' # logger.info("for device "+self.p4dev.devName+" Packet built for rank : "+str(rank)+" port :"+str(port)+" minindex : "+ # str(rankMinIndex)+" maxindex :"+str(rankMaxIndex)+" portIndex "+str(newPortIndex)+" Packet type "+(str(isDelete))+ " Bitmask "+str(bitmask)) rawPktContent = (255).to_bytes( 2, 'big') # first 2 byte egressport and padding if (isDelete == True): rawPktContent = rawPktContent + (128).to_bytes(1, 'big') topKPathFalgs = 128 else: rawPktContent = rawPktContent + (0).to_bytes(1, 'big') topKPathFalgs = 0 # rawPktContent = rawPktContent + (linkID).to_bytes(4,'big') # rawPktContent = rawPktContent + (bitmask).to_bytes(4,'big') # rawPktContent = rawPktContent + (level_to_link_id_store_index).to_bytes(4,'big') packet_out_req = p4runtime_pb2.StreamMessageRequest() packet_out_port_hex = packet_out_port.to_bytes(length=2, byteorder="big") packet_out = p4runtime_pb2.PacketOut() egress_physical_port = packet_out.metadata.add() egress_physical_port.metadata_id = 1 egress_physical_port.value = packet_out_port_hex topKPathFalgs_metadata_field = packet_out.metadata.add() topKPathFalgs_metadata_field.metadata_id = 3 topKPathFalgs_metadata_field.value = (topKPathFalgs).to_bytes(1, 'big') bitmask_metadata_field = packet_out.metadata.add() bitmask_metadata_field.metadata_id = 4 bitmask_metadata_field.value = (bitmask).to_bytes(4, 'big') rank_metadata_field = packet_out.metadata.add() rank_metadata_field.metadata_id = 5 rank_metadata_field.value = (rank).to_bytes(4, 'big') port_metadata_field = packet_out.metadata.add() port_metadata_field.metadata_id = 6 port_metadata_field.value = (port).to_bytes(4, 'big') rankMaxIndex_metadata_field = packet_out.metadata.add() rankMaxIndex_metadata_field.metadata_id = 7 rankMaxIndex_metadata_field.value = (rankMaxIndex).to_bytes(4, 'big') rankMinIndex_metadata_field = packet_out.metadata.add() rankMinIndex_metadata_field.metadata_id = 8 rankMinIndex_metadata_field.value = (rankMinIndex).to_bytes(4, 'big') newPortIndex_metadata_field = packet_out.metadata.add() newPortIndex_metadata_field.metadata_id = 9 newPortIndex_metadata_field.value = (newPortIndex).to_bytes(4, 'big') packet_out.payload = rawPktContent packet_out_req.packet.CopyFrom(packet_out) return packet_out_req
def sendPacketOutMigration(self, flowID, migProcessFlowID, migSubProtocol, migSequenceID, migVNFID, migSessionID, networkInfo): # allocate buffers: # buff_migSubProtocol = array('b', b' '*8) # buff_migSequenceID = array('b',b' '* 16) # buff_migVNFID = array('b',b' '* 8) # buff_migSrcSw = array('b',b' '*8) # buff_migDstsw = array('b',b' '*8) # buff_migStatus = array('b',b' '*8) # buff_migSessionID = array('b',b' '*8) sleep(self.controlPlaneDelay) buff_indicator = bitstring.BitArray(uint=int(0x3341), length=16) buff_migSubProtocol = bitstring.BitArray(uint=int(migSubProtocol), length=8) buff_migSequenceID = bitstring.BitArray(uint=int(migSequenceID), length=16) buff_migVNFID = bitstring.BitArray(uint=int(migVNFID), length=8) buff_migSessionID = bitstring.BitArray(uint=int(migSessionID), length=8) buff_migProcessFlowID = bitstring.BitArray(uint=int(migProcessFlowID), length=32) buff_flowID = bitstring.BitArray( uint=int(flowID), length=32) # the flowid that is migrated header = buff_migSubProtocol + buff_migSequenceID + buff_migVNFID + buff_migSessionID if 'srcIP' in networkInfo and 'dstIP' in networkInfo and 'srcPort' in networkInfo and 'dstPort' in networkInfo and 'ipProtocol' in networkInfo: buff_migSrcIP = bitstring.BitArray(uint=int( struct.unpack("!I", socket.inet_aton(networkInfo['srcIP']))[0]), length=32) buff_migDstIP = bitstring.BitArray(uint=int( struct.unpack("!I", socket.inet_aton(networkInfo['dstIP']))[0]), length=32) buff_migSrcPort = bitstring.BitArray(uint=int( networkInfo['srcPort']), length=16) buff_migDstPort = bitstring.BitArray(uint=int( networkInfo['dstPort']), length=16) buff_migIPProtocol = bitstring.BitArray(uint=int( networkInfo['ipProtocol']), length=8) netInfoHeader = buff_flowID + buff_migSrcIP + buff_migDstIP + buff_migSrcPort + buff_migDstPort + buff_migIPProtocol header = header + netInfoHeader # else: # buff_ind = bitstring.BitArray(uint=int(0x1433), length=16) # netInfoHeader = buff_ind + buff_flowID # header = header + netInfoHeader #print "sending packetout to switch %s" % self.name packet_out_req = p4runtime_pb2.PacketOut() packet_out_req.payload = buff_indicator.tobytes( ) + buff_migProcessFlowID.tobytes() + header.tobytes() req = p4runtime_pb2.StreamMessageRequest() req.packet.CopyFrom(packet_out_req) #print "sending packet %s to switch %s" % (req.packet.payload.encode('hex'), self.name) self.stream_out_q.put(req)
def packet_out_msg(self,pl,meta): return p4runtime_pb2.PacketOut(payload=pl,metadata=meta)
def get_stream_packet(self, type_, timeout=1): start = time.time() try: while True: remaining = timeout - (time.time() - start) if remaining < 0: break msg = self.stream_in_q.get(timeout=remaining) if not msg.HasField(type_): continue return msg except: # timeout expired pass return None def send_packet_out(self, packet): packet_out_req = p4runtime_pb2.StreamMessageRequest() packet_out_req.packet.CopyFrom(packet) self.stream_out_q.put(packet_out_req) if __name__ == '__main__': test = Test() test.set_up_stream() test.update_config() if args.loopback: packet_out = p4runtime_pb2.PacketOut() packet_out.payload = "\xab" * 100 test.send_packet_out(packet_out) test.get_packet_in() test.tear_down_stream()
def main(p4info_file_path, bmv2_file_path): # Instantiate a P4Runtime helper from the p4info file mac_to_port = defaultdict(dict) p4info_helper = helper.P4InfoHelper(p4info_file_path) try: # Create a switch connection object for s1 and s2; # this is backed by a P4Runtime gRPC connection. # Also, dump all P4Runtime messages sent to switch to given txt files. s1 = bmv2.Bmv2SwitchConnection( name='s0', address='127.0.0.1:50051', device_id=1) # Send master arbitration update message to establish this controller as # master (required by P4Runtime before performing any other write operation) s1.MasterArbitrationUpdate() # Install the P4 program on the switches s1.SetForwardingPipelineConfig(p4info=p4info_helper.p4info, bmv2_json_file_path=bmv2_file_path) print "Installed P4 Program using SetForwardingPipelineConfig on s1" # Write the rules that tunnel traffic from h1-h2 to s1 # writeIpv4Rules(p4info_helper, sw_id=s1, dst_ip_addr="10.10.10.1", port = 1) # writeIpv4Rules(p4info_helper, sw_id=s1, dst_ip_addr="10.10.10.2", port = 2) # writeIpv4Rules(p4info_helper, sw_id=s1, dst_ip_addr="10.10.3.3", port = 3) # readTableRules(p4info_helper, s1) mc_group_entry = p4info_helper.buildMulticastGroupEntry(1, replicas=[ {'egress_port': 1, 'instance': 1}, {'egress_port': 2, 'instance': 2}, {'egress_port': 3, 'instance': 3}, {'egress_port': 4, 'instance': 4}, {'egress_port': 5, 'instance': 5}, {'egress_port': 64, 'instance': 64} ]) s1.WritePREEntry(mc_group_entry) print "Installed mgrp on s1." writeBroadcastRules(p4info_helper, s1) readTableRules(p4info_helper, s1) lldp_thread = LLDP_Thread(s1) # lldp_thread.run() # lldp_thread.start() # counter = 0 while True: packetin = s1.PacketIn() # counter += 1 payload = packetin.packet.payload pkt = Ether(_pkt=payload[12:]) # metadata = packetin.packet.metadata[0] # metadata_id = metadata.metadata_id # port = metadata.value # pkt_type = packetin.packet.metadata[1].value zeros = struct.unpack(">q", payload[:8])[0] port = struct.unpack(">H", payload[8:10])[0] type = struct.unpack(">H", payload[10:12])[0] if zeros == 0: pkt_eth_src = pkt.getlayer(Ether).src pkt_eth_dst = pkt.getlayer(Ether).dst ether_type = pkt.getlayer(Ether).type # self send lldp if type == 5: pass elif type == 4: pass else: lldp_thread.run() # if pkt_eth_src in mac_to_port[s1.name]: # writeIpv4Rules(p4info_helper,s1,pkt_eth_src,mac_to_port[s1.name][pkt_eth_src]) # if ether_type == 2048 or ether_type == 2054: # writeIpv4Rules(p4info_helper, s1, pkt_eth_src, port) mac_to_port[s1.name][pkt_eth_src] = port if pkt_eth_dst not in mac_to_port[s1.name]: writeFloodingRules(p4info_helper, s1, pkt_eth_src, pkt_eth_dst) else: writeIpv4Rules(p4info_helper, s1, pkt_eth_src, pkt_eth_dst, mac_to_port[s1.name][pkt_eth_dst]) writeIpv4Rules(p4info_helper, s1, pkt_eth_dst, pkt_eth_src, mac_to_port[s1.name][pkt_eth_src]) readTableRules(p4info_helper, s1) packet_out = p4runtime_pb2.PacketOut() packet_out.payload = payload[12:] # def packet_Out(s1,packetout): # s1.PacketOut(packetout) # thread.start_new_thread(packet_Out,(s1,packet_out)) # packet_out.metadata = metadata s1.PacketOut(packet_out) # if counter % 10 == 0: else: pass except KeyboardInterrupt: print " Shutting down." except grpc.RpcError as e: printGrpcError(e) ShutdownAllSwitchConnections()