55import sys
66import asyncio
77import traceback
8+ import time
89
9- from collections import deque
1010from collections import Counter
1111from scapy .all import *
1212
@@ -180,10 +180,24 @@ def addFlowRule( ingress_sw, src_ip_addr, dst_ip_addr, protocol, port, new_dscp,
180180 ingress_sw .WriteTableEntry (table_entry )
181181 print ("Installed ingress rule on %s" % ingress_sw .name )
182182
183+ def deleteFlowRule (notif ):
184+ notif ["sw" ].DeleteTableEntry (notif ["idle" ].table_entry [0 ])
185+ print ("Deleted ingress rule on %s" % notif ["sw" ].name )
186+
187+ def packetOutMetadataList (opcode , reserved1 , operand0 ):
188+ # This function does not use the generated contents of the P4Info
189+ # file to map PacketOut metadata fields to indices. If you change
190+ # the PacketOut metadata format in the P4 program, this code must
191+ # be manually updated to match.
192+ return [{"value" : opcode , "bitwidth" : 8 },
193+ {"value" : reserved1 , "bitwidth" : 8 },
194+ {"value" : operand0 , "bitwidth" : 32 }]
195+
183196def sendPacketOut (sw ,payload , metadatas ):
184197 # TODO: Implement the function logic to send a packet-out message
198+ sw .PacketOut (payload , metadatas )
185199
186- async def readTableRules (p4info_helper , sw ):
200+ def readTableRules (p4info_helper , sw ):
187201 """
188202 Reads the table entries from all tables on the switch.
189203
@@ -199,7 +213,7 @@ async def readTableRules(p4info_helper, sw):
199213 print (entry )
200214 print ('-----' )
201215
202- async def printCounter (p4info_helper , sw , counter_name , index ):
216+ def printCounter (p4info_helper , sw , counter_name , index ):
203217 """
204218 Reads the specified counter at the given index from the switch. In our
205219 program, the index is derived from the first 6 bits of the IP destination address.
@@ -224,17 +238,18 @@ async def printCounter(p4info_helper, sw, counter_name, index):
224238
225239 if e .code () == grpc .StatusCode .UNKNOWN :
226240 print (f"Unknown gRPC error from { sw .name } . Retrying..." )
227- await asyncio .sleep (2 )
241+ time .sleep (2 )
228242
229243 except Exception as e :
230244 print (f"[Unexpected Error in printCounter for { sw .name } ]: { e } " )
231245 traceback .print_exc ()
232- await asyncio .sleep (2 )
246+ time .sleep (2 )
233247
234- async def processPacket (message ):
235- payload = message ["packet-in" ].packet .payload
236- packet = message ["packet-in" ].packet
237- print ("Received %d PacketIn messages" % (len (payload )))
248+ def processPacket (message ):
249+ payload = message ["packet-in" ].payload
250+ packet = message ["packet-in" ]
251+ print ("Received PacketIn message of length %d bytes from switch %s"
252+ "" % (len (payload ), message ["sw" ].name ))
238253 if len (payload ) > 0 :
239254 i = 0
240255 pkt = Ether (payload )
@@ -267,7 +282,9 @@ async def processPacket(message):
267282 new_dscp_int = 5
268283 global_data ['index' ] = int (pkt [IP ].dst .split ('.' )[3 ])
269284 dst_eth_addr = global_data [ip_da_str ]
270- metadatas = [{ "value" : 0 , "bitwidth" : 8 }, { "value" : 3 , "bitwidth" : 32 }]
285+ metadatas = packetOutMetadataList (
286+ global_data ['controller_opcode_name2int' ]['SEND_TO_PORT_IN_OPERAND0' ],
287+ 0 , dest_port_int )
271288 sendPacketOut (message ["sw" ], payload , metadatas )
272289 addFlowRule (message ["sw" ],
273290 src_ip_addr ,
@@ -287,21 +304,21 @@ async def processPacket(message):
287304async def processNotif (notif_queue ):
288305 while True :
289306 notif = await notif_queue .get ()
290-
307+ print ( notif )
291308 if notif ["type" ] == "packet-in" :
292- await processPacket (notif )
293- await printCounter (global_data ['p4info_helper' ], notif ["sw" ], 'MyIngress.ingressPktOutCounter' , global_data ['index' ])
294- await printCounter (global_data ['p4info_helper' ], notif ["sw" ], 'MyEgress.egressPktInCounter' , global_data ['index' ])
295- await readTableRules (global_data ['p4info_helper' ], notif ["sw" ])
309+ processPacket (notif )
310+ printCounter (global_data ['p4info_helper' ], notif ["sw" ], 'MyIngress.ingressPktOutCounter' , global_data ['index' ])
311+ printCounter (global_data ['p4info_helper' ], notif ["sw" ], 'MyEgress.egressPktInCounter' , global_data ['index' ])
312+ readTableRules (global_data ['p4info_helper' ], notif ["sw" ])
296313 elif notif ["type" ] == "idle-notif" :
297- print (notif [ "idle" ] )
314+ deleteFlowRule (notif )
298315
299316 notif_queue .task_done ()
300317
301318async def packetInHandler (notif_queue ,sw ):
319+ # TODO: Implement the function logic to handle a packet-in message
302320 while True :
303321 try :
304- # TODO: Implement the function logic to handle a packet-in message
305322
306323 except grpc .RpcError as e :
307324 print (f"[gRPC Error in packetInHandler for { sw .name } ]" )
@@ -318,6 +335,8 @@ async def packetInHandler(notif_queue,sw):
318335
319336async def idleTimeHandler (notif_queue ,sw ):
320337 # TODO: Implement the function logic to handle idle timeout notification
338+ while True :
339+
321340
322341def printGrpcError (e ):
323342 print ("gRPC Error:" , e .details (), end = ' ' )
@@ -375,6 +394,8 @@ async def main(p4info_file_path, bmv2_file_path):
375394
376395 global_data ['punt_reason_name2int' ], global_data ['punt_reason_int2name' ] = \
377396 serializableEnumDict (p4info_helper .p4info , 'PuntReason_t' )
397+ global_data ['controller_opcode_name2int' ], global_data ['controller_opcode_int2name' ] = \
398+ serializableEnumDict (p4info_helper .p4info , 'ControllerOpcode_t' )
378399
379400 try :
380401 replicas = [{ "egress_port" : global_data ['CPU_PORT' ], "instance" : 1 }]
@@ -427,4 +448,4 @@ async def main(p4info_file_path, bmv2_file_path):
427448 parser .print_help ()
428449 print ("\n BMv2 JSON file not found: %s\n Have you run 'make'?" % args .bmv2_json )
429450 parser .exit (1 )
430- asyncio .run (main (args .p4info , args .bmv2_json ))
451+ asyncio .run (main (args .p4info , args .bmv2_json ))
0 commit comments