Open Ethernet Networking (OpEN) API Guide and Reference Manual  3.10.0.3
rx_pkt_example.py
1 /*! \file rx_pkt_example.py
2  */
3 
4 #!/mnt/fastpath/usr/bin/python
5 
6 """rx_pkt_example.py: OpEN API Packet Receive example"""
7 
8 import OpEN_py as OpEN
9 from OpENUtil import *
10 import socket
11 import struct
12 import sys
13 import os
14 import ctypes
15 from sys import version_info
16 
17 open_ = OpENUtil()
18 
19 #
20 # Copyright 2016 Broadcom.
21 #
22 # Licensed under the Apache License, Version 2.0 (the "License")
23 # you may not use this file except in compliance with the License.
24 # You may obtain a copy of the License at
25 #
26 # http://www.apache.org/licenses/LICENSE-2.0
27 #
28 # Unless required by applicable law or agreed to in writing, software
29 # distributed under the License is distributed on an "AS IS" BASIS,
30 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 # See the License for the specific language governing permissions and
32 # limitations under the License.
33 #
34 
35 #
36 # Python 2.6.6
37 #
38 
39 DESTINATION_MAC = 'Destination MAC'
40 SOURCE_MAC = 'Source MAC'
41 VLAN_ID = 'VLAN ID'
42 VLAN_PRIORITY = 'VLAN Priority'
43 ETHER_TYPE = 'Ether Type'
44 DESTINATION_IP = 'Destination IPv4'
45 DESTINATION_IP_MASK = 'Destination Mask'
46 SOURCE_IP = 'Source IPv4'
47 SOURCE_IP_MASK = 'Source IPv4 Mask'
48 DESTINATION_IPV6 = 'Destination IPV6'
49 DESTINATION_IPV6_MASK = 'Destination IPV6 Mask'
50 SOURCE_IPV6 = 'Source IPV6'
51 SOURCE_IPV6_MASK = 'Source IPV6 Mask'
52 DONE = 'Done'
53 
54 def ip_to_int(addr) :
55  """Convert ipv4 string to integer"""
56 
57  return struct.unpack("!I", socket.inet_aton(addr))[0]
58 
59 def ipv6_to_int(addr) :
60  """Convert ipv6 string to integer"""
61 
62  str_ = socket.inet_pton(socket.AF_INET6, addr)
63  a, b = struct.unpack('!2Q', str_)
64  return (a << 64) | b
65 
66 def print_sanity_results(result, test, msg, feat) :
67  """Print overall comparison results"""
68 
69  if result == OpEN.OPEN_E_UNAVAIL:
70  print("Sanity test skipped.")
71  elif result == OpEN.OPEN_E_EXISTS:
72  print("Sanity Skipped (already exists) - %s - %s." % (msg, feat))
73  elif result == OpEN.OPEN_E_NONE and test == True:
74  print("Sanity Success - %s - %s." % (msg, feat))
75  else:
76  print("Sanity Failure - %s - %s." % (msg, feat))
77 
78 def print_bad_result(result, msg) :
79  """Print some general error messages if the result is bad"""
80 
81  if result == OpEN.OPEN_E_UNAVAIL:
82  print("Feature not supported - %s (err %d)." % (msg, result))
83  elif result == OpEN.OPEN_E_NOT_FOUND:
84  print("Test Skipped (not found) - ", msg)
85  elif result != OpEN.OPEN_E_NONE:
86  print("Test Failure - %s (err %d)." % (msg, result))
87 
88 def get_mac_address(prompt) :
89  """Get a MAC address from the user and return it as an unsigned char"""
90 
91  while True:
92  try:
93  mac = raw_input(prompt)
94  macstr = mac.replace(':', '').decode('hex')
95  if len(macstr) == 6:
96  return open_.getUCharBuffer(len(macstr),macstr)
97  else:
98  print("Invalid MAC address.")
99  except Exception as e:
100  print("%s" % str(e))
101 
102 def get_ipv4_address(prompt) :
103  """ get an IP address from user and return it as int"""
104 
105  while True:
106  try:
107  address = raw_input(prompt)
108  return ip_to_int(address)
109  except Exception as e:
110  print("%s" % str(e))
111  except:
112  print("Invalid IPv4 address.")
113 
114 def get_ipv6_address(prompt) :
115  """ get an IP address from user and return it as open_inet_addr_t"""
116 
117  addr = OpEN.open_inet_addr_t()
118 
119  if not socket.has_ipv6:
120  print_bad_result(OpEN.OPEN_E_UNAVAIL, prompt)
121  return addr
122 
123  while True:
124  try:
125  address = raw_input(prompt)
126  addr.addr.ipv6 = ipv6_to_int(address)
127  addr.family = socket.AF_INET6
128  return addr
129  except Exception as e:
130  print("%s" % str(e))
131  except:
132  print("Invalid IPv6 address.")
133 
134 def done() :
135  """ """
136 
137 def receive_packets(self, agent_num, pkt_cnt, log_file) :
138  """Create a socket end-point to receive frames
139  Display packets received, else write to log_file if defined. """
140 
141  if log_file == None: log = False
142  else: log = True
143 
144  # Make sure agent isn't already registered
145  OpEN.openapiExtAgentPktUnregister(agent_num)
146 
147  # Register new agent
148  agent_name = "Test Agent"
149  try:
150  agent_string = open_.getStringBuffer(len(agent_name) + 1, agent_name)
151  except OpENBufferSizeError:
152  print("receive_packets: getStringBuffer raised OpENBufferSizeError")
153  return
154  except TypeError:
155  print("receive_packets: getStringBuffer raised TypeError")
156  return
157  agent_buff = OpEN.open_buffdesc()
158  agent_buff.pstart = agent_string
159  agent_buff.size = len(agent_name) + 1
160  result = OpEN.openapiExtAgentPktRegister(agent_num, agent_buff, OpEN.OPEN_TCAM_EXT_AGENT_PKT_RECEIVE)
161  print_sanity_results(result, True, 'openapiExtAgentPktRegister', "Register External Agent: (%s)" % agent_name)
162 
163  if result != OpEN.OPEN_E_NONE: return
164 
165  # Socket file name is based on agent id
166  fn = '/tmp/rx.%05d' % agent_num
167 
168  # Remove previous socket file (must not exist)
169  try:
170  os.unlink(fn)
171  except:
172  pass
173 
174  s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
175  s.bind(fn)
176 
177  print("Receiving Packets...")
178  if log: f = open(log_file, 'w')
179 
180  pkt_p = OpEN.new_open_sysExtAgentPktRxDesc_tp()
181  idx = 0
182 
183  while (idx < pkt_cnt):
184  data, addr = s.recvfrom(OpEN.OPEN_TXRX_MAX_FRAME_SIZE + 64)
185  OpEN.buf_to_open_sysExtAgentPktRxDesc_t(data, pkt_p)
186  pkt = OpEN.open_sysExtAgentPktRxDesc_tp_value(pkt_p)
187 
188  if log:
189  f.write("\nPacket received from ifNum %d, pktLen %d" % (pkt.rxIfNum, pkt.pktLength))
190  f.write("\nPacket content:")
191  else:
192  print("\nPacket #%d Version:%d Received from ifNum %d, pktLen %d" % (idx, pkt.version, pkt.rxIfNum, pkt.pktLength))
193  print("Packet content:")
194 
195  if version_info >= (3,0,0):
196  for i in range(0, pkt.pktLength-1):
197  octet = data[pkt.descLen+i:pkt.descLen+i+1].encode('hex')
198  if log: f.write('%s ' % octet)
199  else: print(octet, end=" ")
200  else:
201  for i in xrange(0, pkt.pktLength-1):
202  octet = data[pkt.descLen+i:pkt.descLen+i+1].encode('hex')
203  if log: f.write('%s ' % octet)
204  else: print(octet, end=" ")
205 
206  if log: f.write('\n')
207  else: print()
208 
209  idx += 1
210 
211  OpEN.openapiExtAgentPktUnregister(agent_num)
212  OpEN.delete_open_sysExtAgentPktRxDesc_tp(pkt_p)
213  s.close()
214  if log: f.close()
215 
216 class Policy :
217  """TCAM API policy"""
218 
219  def __init__(self, client) :
220  self.m_client = client
221  self.m_open_policy = OpEN.open_tcamApiPolicy_t()
222  self.m_initialized = False
223  self.m_handle = None
224 
225  def __del__(self):
226  if self.m_handle:
227  OpEN.delete_OPEN_TCAM_API_POLICYID_tp(self.m_handle)
228 
229  def initialize(self) :
230  """Initialize API and get/store the API versioning in the header"""
231 
232  result = OpEN.openapiTcamApiInit(self.m_client)
233  if result == OpEN.OPEN_E_NONE:
234  version = OpEN.open_tcam_version_t()
235  result = OpEN.openapiTcamApiVersionGet(self.m_client, version)
236  if result == OpEN.OPEN_E_NONE:
237  self.m_open_policy.policyHeader.versionInfo.versionMajor = version.versionMajor
238  self.m_open_policy.policyHeader.versionInfo.versionMinor = version.versionMinor
239  self.m_open_policy.policyHeader.headerLen = sys.getsizeof(self.m_open_policy.policyHeader)
240  self.m_initialized = True
241 
242  def match_dst_mac(self) :
243  """Prompt user for destination mac address and save it"""
244  self.m_open_policy.matchDstMac = get_mac_address(DESTINATION_MAC + ' (xx:xx:xx:xx:xx:xx) : ')
245 
246  def match_src_mac(self) :
247  """Prompt the user for source mac address and save it"""
248  self.m_open_policy.matchSrcMac = get_mac_address(SOURCE_MAC + ' (xx:xx:xx:xx:xx:xx) : ')
249 
250  def match_vlan(self) :
251  """Prompt user for vlan and save it"""
252 
253  while True:
254  try:
255  self.m_open_policy.matchVlanVal = int(raw_input(VLAN_ID + ' : '))
256  break
257  except Exception as e:
258  print("%s" % str(e))
259  except:
260  print("Invalid VLAN.")
261 
262  def match_vlan_priority(self) :
263  """Prompt user for vlan priority and save it"""
264 
265  while True:
266  try:
267  self.m_open_policy.matchVlanPrio = int(raw_input(VLAN_PRIORITY + ' : '))
268  break
269  except Exception as e:
270  print("%s" % str(e))
271  except:
272  print("Invalid VLAN priority.")
273 
274  def match_ether_type(self) :
275  """Prompt user for ether type and save it"""
276 
277  while True:
278  try:
279  hexstr = raw_input(ETHER_TYPE + ' (xx) : ')
280  self.m_open_policy.matchEthType = int(hexstr[0:2], 16)
281  break
282  except Exception as e:
283  print("%s" % str(e))
284  except:
285  print("Invalid Ether type.")
286 
287  def match_dst_ipv4(self) :
288  """Prompt user for IP and save it"""
289 
290  self.m_open_policy.matchDstIp = get_ipv4_address(DESTINATION_IP + ' : ')
291  self.m_open_policy.matchDstIpMask = get_ipv4_address(DESTINATION_IP_MASK + ' : ')
292 
293  def match_src_ipv4(self) :
294  """Prompt user for IP and save it"""
295  self.m_open_policy.matchSrcIp = get_ipv4_address(SOURCE_IP + ' : ')
296  self.m_open_policy.matchSrcIpMask = get_ipv4_address(SOURCE_IP_MASK + ' : ')
297 
298  def match_dst_ipv6(self) :
299  """Prompt user for IP and save it"""
300 
301  self.m_open_policy.matchDstIpv6Addr = get_ipv6_address(DESTINATION_IPV6 + ' : ')
302  self.m_open_policy.matchDstIpv6Mask = get_ipv6_address(DESTINATION_IPV6_MASK + ' : ')
303 
304  def match_src_ipv6(self) :
305  """Prompt user for IP and save it"""
306 
307  self.m_open_policy.matchSrcIpv6Mask = get_ipv6_address(SOURCE_IPV6 + ' : ')
308  self.m_open_policy.matchSrcIpv6Mask = get_ipv6_address(SOURCE_IPV6_MASK + ' : ')
309 
310  def get_priority_and_type(self) :
311  """Prompt user for policy priority and type and save it"""
312 
313  while True:
314  try:
315  policy_priority = int(raw_input("Enter policy priority : "))
316  self.m_open_policy.policyPrio = policy_priority
317  break
318  except:
319  print("Invalid priority, priority must be numeric.")
320 
321  while True:
322  try:
323  policy_type = int(raw_input("Enter policy type (1:OpenFlow 2:Gen IPv6 3:Egress) : "))
324  if policy_type == 1:
325  self.m_open_policy.policyType = OpEN.OPEN_TCAM_POLICY_TYPE_OPENFLOW
326  break
327  elif policy_type == 2:
328  self.m_open_policy.policyType = OpEN.OPEN_TCAM_POLICY_TYPE_GEN
329  break
330  elif policy_type == 3:
331  self.m_open_policy.policyType = OpEN.OPEN_TCAM_POLICY_TYPE_EGRESS
332  break
333  print("Invalid type.")
334  except:
335  print("Invalid type, type must be numeric.")
336 
337  def get_classifiers(self) :
338  """Prompt the user for policy classifiers and save them.
339  The input loops until the user is done"""
340 
341  type_menu = {
342  1: self.match_dst_mac,
343  2: self.match_src_mac,
344  3: self.match_vlan,
345  4: self.match_vlan_priority,
346  5: self.match_ether_type,
347  6: self.match_dst_ipv4,
348  7: self.match_src_ipv4,
349  8: self.match_dst_ipv6,
350  9: self.match_src_ipv6,
351  10: done
352  }
353 
354  while True:
355  try:
356  print("Enter classification types")
357  print("--------------------------")
358  print("1: Match", DESTINATION_MAC)
359  print("2: Match", SOURCE_MAC)
360  print("3: Match", VLAN_ID)
361  print("4: Match", VLAN_PRIORITY)
362  print("5: Match", ETHER_TYPE)
363  print("6: Match", DESTINATION_IP)
364  print("7: Match", SOURCE_IP)
365  print("8: Match", DESTINATION_IPV6)
366  print("9: Match", SOURCE_IPV6)
367  print("10:", DONE)
368 
369  type = input("Enter selection : ")
370  if type == 10:
371  break
372  if type in type_menu:
373  type_menu[type]()
374 
375  except:
376  pass
377 
378  def get_actions(self, agent_num) :
379  """The policy action is hard-coded in this example"""
380 
381  self.m_open_policy.actionType |= OpEN.OPEN_TCAM_ACTION_REDIRECT_CPU
382  self.m_open_policy.ruleNum = agent_num
383 
384  def create(self) :
385  """Create the actual policy on the device """
386 
387  handle_p = OpEN.new_OPEN_TCAM_API_POLICYID_tp()
388 
389  result = OpEN.openapiTcamPolicyCreate(self.m_client, self.m_open_policy, handle_p)
390  if result == OpEN.OPEN_E_NONE:
391  print()
392  print("Policy successfully added.")
393  self.m_handle = handle_p
394  else:
395  print()
396  print("Error: Policy could not be created")
397 
398  def get_interface(self) :
399  """ Prompt for interface and add it to the policy"""
400 
401  intf_p = OpEN.new_uint32_tp()
402 
403  while True:
404  try:
405  interface = raw_input("Enter interface name (slot/port) : ")
406  try:
407  name_str = open_.getStringBuffer(len(interface) + 1, interface)
408  except OpENBufferSizeError:
409  print("get_interface: getStringBuffer raised OpENBufferSizeError")
410  return
411  except TypeError:
412  print("get_interface: getStringBuffer raised TypeError")
413  return
414  name_buff = OpEN.open_buffdesc()
415  name_buff.pstart = name_str
416  name_buff.size = len(interface)+1
417 
418  result = OpEN.openapiIfNumGet(self.m_client, name_buff, intf_p)
419  print_bad_result(result, "get interface")
420  if result == OpEN.OPEN_E_NONE:
421  intf = OpEN.uint32_tp_value(intf_p)
422  result = OpEN.openapiTcamPolicyIntfAdd(self.m_client, self.m_handle, intf)
423  print_bad_result(result, "add interface")
424  break
425  except:
426  print("Invalid Interface.")
427 
428  OpEN.delete_uint32_tp(intf_p)
429 
430 class RxPktExample :
431  """Packet transmission """
432 
433  def __init__(self, client) :
434  self.m_client = client
435 
436  def test_rx_pkt(self, agent_num, pkt_cnt, log_file) :
437  """Instantiate and create a policy and assign it to an interface.
438  Establish a server socket to accept packets from the agent."""
439 
440  policy = Policy(self.m_client)
441  policy.initialize()
442  policy.get_priority_and_type()
443  policy.get_classifiers()
444  policy.get_actions(agent_num)
445  policy.create()
446  policy.get_interface()
447  receive_packets(self, agent_num, pkt_cnt, log_file)
448 
449 def main(argv) :
450  """Demonstrate OpEN usage for Packet API"""
451 
452  # logfile is optional
453  if len(argv) < 2 or len(argv) > 3:
454  print("rx_pkt_example.py <agentnum> <packetcount> [logfile]")
455  sys.exit()
456 
457  try:
458  agent_num = int(argv[0])
459  except:
460  print("Invalid agent number, <agentnum> must be numeric.")
461  sys.exit()
462 
463  try:
464  packet_count = int(argv[1])
465  except:
466  print("Invalid packet count, <packetcount> must be numeric.")
467  sys.exit()
468 
469  try:
470  log_file = argv[2]
471  fp = open (log_file, 'w')
472  fp.close()
473  except:
474  log_file = None
475 
476  ret = open_.connect("tx_pkt_example")
477  if ret == OpEN.OPEN_E_NONE:
478  open_.getNetworkOSVersion()
479  client = open_.get_client()
480  example = RxPktExample(client)
481  example.test_rx_pkt(agent_num, packet_count, log_file)
482  open_.terminate()
483  else:
484  print("Unable to connect")
485 
486 if __name__ == '__main__':
487  main(sys.argv[1:])
488 
489