2 # Copyright (c) 2016 Cisco and/or its affiliates.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 # Import C API shared object
18 from __future__ import print_function
20 import signal, logging, os, sys
23 scriptdir = os.path.dirname(os.path.realpath(__file__))
24 sys.path.append(scriptdir)
26 from vpp_api_base import *
28 # Import API definitions. The core VPE API is imported into main namespace
31 vpe = sys.modules['vpe']
35 logging.warning('vpp_api.read failed')
38 id = unpack('>H', msg[0:2])
39 logging.debug('Received message', id[0])
40 if id[0] == memclnt.VL_API_RX_THREAD_EXIT:
41 logging.info("We got told to leave")
45 # Decode message and returns a tuple.
47 logging.debug('api_func', api_func_table[id[0]])
48 r = api_func_table[id[0]](msg)
50 logging.warning('Message decode failed', id[0])
53 if 'context' in r._asdict():
58 # XXX: Call provided callback for event
59 # Are we guaranteed to not get an event during processing of other messages?
60 # How to differentiate what's a callback message and what not? Context = 0?
62 if not is_waiting_for_reply():
63 event_callback_call(r)
67 # Collect results until control ping
69 if id[0] == vpe.VL_API_CONTROL_PING_REPLY:
70 results_event_set(context)
71 waiting_for_reply_clear()
73 if not is_results_context(context):
74 logging.warning('Not expecting results for this context', context)
76 if is_results_more(context):
77 results_append(context, r)
80 results_set(context, r)
81 results_event_set(context)
82 waiting_for_reply_clear()
85 signal.alarm(3) # 3 second
86 rv = vpp_api.connect(name, msg_handler)
88 logging.info("Connect:", rv)
91 # Assign message id space for plugins
98 rv = vpp_api.disconnect()
99 logging.info("Disconnected")
102 # CLI convenience wrapper
105 r = cli_inband(len(cmd), cmd)
106 return r.reply[0].decode().rstrip('\x00')
108 def register_event_callback(callback):
109 event_callback_set(callback)
111 def plugin_name_to_id(plugin, name_to_id_table, base):
113 m = globals()[plugin]
115 m = sys.modules[plugin]
116 for name in name_to_id_table:
117 setattr(m, name, name_to_id_table[name] + base)
119 def plugin_map_plugins():
121 if p == 'memclnt' or p == 'vpe':
128 version = plugins[p]['version']
129 name = p + '_' + format(version, '08x')
130 r = memclnt.get_first_msg_id(name.encode('ascii'))
132 ## TODO: Add error handling
134 print('Failed getting first msg id for:', p)
138 base = r.first_msg_id
139 msg_id_base_set = plugins[p]['msg_id_base_set']
140 msg_id_base_set(base)
141 plugins[p]['base'] = base
142 func_table = plugins[p]['func_table']
144 for entry in func_table:
145 api_func_table.insert(i, entry)
147 plugin_name_to_id(p, plugins[p]['name_to_id_table'], base)
152 memclnt.msg_id_base_set(1)
153 plugins['memclnt']['base'] = 1
154 msg_id_base_set(len(plugins['memclnt']['func_table']) + 1)
155 plugins['vpe']['base'] = len(plugins['memclnt']['func_table']) + 1
157 api_func_table.append(None)
158 api_func_table[1:] = plugins['memclnt']['func_table'] + plugins['vpe']['func_table']
159 plugin_name_to_id('memclnt', plugins['memclnt']['name_to_id_table'], 1)
160 plugin_name_to_id('vpe', plugins['vpe']['name_to_id_table'], plugins['vpe']['base'])
161 #logging.basicConfig(level=logging.DEBUG)