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