blob: 9c2d2b2ba2a3e2b42701e371d462aa9066b169ac [file] [log] [blame]
Ole Troan5f9dcff2016-08-01 04:59:13 +02001#
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:
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
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.
14
15#
16# Import C API shared object
17#
18from __future__ import print_function
19
Ole Troan1732fc12016-08-30 21:03:51 +020020import signal, os, sys
Ole Troan5f9dcff2016-08-01 04:59:13 +020021from struct import *
22
Ole Troan5f9dcff2016-08-01 04:59:13 +020023import vpp_api
24from vpp_api_base import *
25
26# Import API definitions. The core VPE API is imported into main namespace
27import memclnt
Ole Troan57c3d662016-09-12 22:00:32 +020028
29# Cheating a bit, importing it into this namespace as well as a module.
30import vpe
Ole Troan5f9dcff2016-08-01 04:59:13 +020031from vpe import *
Ole Troan5f9dcff2016-08-01 04:59:13 +020032
Ole Troan1732fc12016-08-30 21:03:51 +020033def eprint(*args, **kwargs):
34 print(*args, file=sys.stderr, **kwargs)
35
Ole Troan5f9dcff2016-08-01 04:59:13 +020036def msg_handler(msg):
37 if not msg:
Ole Troan1732fc12016-08-30 21:03:51 +020038 eprint('vpp_api.read failed')
Ole Troan5f9dcff2016-08-01 04:59:13 +020039 return
40
41 id = unpack('>H', msg[0:2])
Ole Troan5f9dcff2016-08-01 04:59:13 +020042 if id[0] == memclnt.VL_API_RX_THREAD_EXIT:
Ole Troan5f9dcff2016-08-01 04:59:13 +020043 return;
44
45 #
46 # Decode message and returns a tuple.
47 #
Ole Troan1732fc12016-08-30 21:03:51 +020048 try:
49 r = api_func_table[id[0]](msg)
50 except:
51 eprint('Message decode failed', id[0], api_func_table[id[0]])
52 raise
Ole Troan5f9dcff2016-08-01 04:59:13 +020053
54 if 'context' in r._asdict():
55 if r.context > 0:
56 context = r.context
57
58 #
59 # XXX: Call provided callback for event
60 # Are we guaranteed to not get an event during processing of other messages?
61 # How to differentiate what's a callback message and what not? Context = 0?
62 #
63 if not is_waiting_for_reply():
64 event_callback_call(r)
65 return
66
67 #
68 # Collect results until control ping
69 #
Ole Troan57c3d662016-09-12 22:00:32 +020070 if id[0] == VL_API_CONTROL_PING_REPLY:
Ole Troan5f9dcff2016-08-01 04:59:13 +020071 results_event_set(context)
72 waiting_for_reply_clear()
73 return
74 if not is_results_context(context):
Ole Troan1732fc12016-08-30 21:03:51 +020075 eprint('Not expecting results for this context', context)
Ole Troan5f9dcff2016-08-01 04:59:13 +020076 return
77 if is_results_more(context):
78 results_append(context, r)
79 return
80
81 results_set(context, r)
82 results_event_set(context)
83 waiting_for_reply_clear()
84
Ole Troan57c3d662016-09-12 22:00:32 +020085def handler(signum, frame):
86 print('Signal handler called with signal', signum)
87 raise IOError("Couldn't connect to VPP!")
88
Ole Troanb8602b52016-10-05 11:10:50 +020089def connect(name, chroot_prefix = None):
Ole Troan57c3d662016-09-12 22:00:32 +020090 # Set the signal handler
91 signal.signal(signal.SIGALRM, handler)
92
Ole Troan5f9dcff2016-08-01 04:59:13 +020093 signal.alarm(3) # 3 second
Ole Troanb8602b52016-10-05 11:10:50 +020094 if not chroot_prefix:
95 rv = vpp_api.connect(name, msg_handler)
96 else:
97 rv = vpp_api.connect(name, msg_handler, chroot_prefix)
98
Ole Troan5f9dcff2016-08-01 04:59:13 +020099 signal.alarm(0)
Ole Troan5f9dcff2016-08-01 04:59:13 +0200100
101 #
102 # Assign message id space for plugins
103 #
Ole Troan57c3d662016-09-12 22:00:32 +0200104 try:
105 plugin_map_plugins()
106 except:
107 return -1
Ole Troan5f9dcff2016-08-01 04:59:13 +0200108 return rv
109
110def disconnect():
111 rv = vpp_api.disconnect()
Ole Troan5f9dcff2016-08-01 04:59:13 +0200112 return rv
113
Ole Troan5f9dcff2016-08-01 04:59:13 +0200114def register_event_callback(callback):
115 event_callback_set(callback)
116
117def plugin_name_to_id(plugin, name_to_id_table, base):
118 try:
119 m = globals()[plugin]
120 except KeyError:
121 m = sys.modules[plugin]
Ole Troan57c3d662016-09-12 22:00:32 +0200122
Ole Troan5f9dcff2016-08-01 04:59:13 +0200123 for name in name_to_id_table:
124 setattr(m, name, name_to_id_table[name] + base)
125
126def plugin_map_plugins():
127 for p in plugins:
128 if p == 'memclnt' or p == 'vpe':
129 continue
130
131 #
132 # Find base
133 # Update api table
134 #
135 version = plugins[p]['version']
136 name = p + '_' + format(version, '08x')
Ole Troan57c3d662016-09-12 22:00:32 +0200137 r = memclnt.get_first_msg_id(name)
Ole Troan5f9dcff2016-08-01 04:59:13 +0200138 if r.retval != 0:
Ole Troan57c3d662016-09-12 22:00:32 +0200139 eprint('Failed getting first msg id for:', p, r, name)
140 raise
Ole Troan5f9dcff2016-08-01 04:59:13 +0200141
142 # Set base
143 base = r.first_msg_id
144 msg_id_base_set = plugins[p]['msg_id_base_set']
145 msg_id_base_set(base)
146 plugins[p]['base'] = base
147 func_table = plugins[p]['func_table']
148 i = r.first_msg_id
Ole Troan1732fc12016-08-30 21:03:51 +0200149 # Insert doesn't extend the table
150 if i + len(func_table) > len(api_func_table):
151 fill = [None] * (i + len(func_table) - len(api_func_table))
152 api_func_table.extend(fill)
Ole Troan5f9dcff2016-08-01 04:59:13 +0200153 for entry in func_table:
Ole Troan1732fc12016-08-30 21:03:51 +0200154 api_func_table[i] = entry
Ole Troan5f9dcff2016-08-01 04:59:13 +0200155 i += 1
156 plugin_name_to_id(p, plugins[p]['name_to_id_table'], base)
157
158#
159# Set up core API
160#
161memclnt.msg_id_base_set(1)
162plugins['memclnt']['base'] = 1
Ole Troan57c3d662016-09-12 22:00:32 +0200163
164# vpe
Ole Troan5f9dcff2016-08-01 04:59:13 +0200165msg_id_base_set(len(plugins['memclnt']['func_table']) + 1)
166plugins['vpe']['base'] = len(plugins['memclnt']['func_table']) + 1
167api_func_table = []
168api_func_table.append(None)
169api_func_table[1:] = plugins['memclnt']['func_table'] + plugins['vpe']['func_table']
170plugin_name_to_id('memclnt', plugins['memclnt']['name_to_id_table'], 1)
171plugin_name_to_id('vpe', plugins['vpe']['name_to_id_table'], plugins['vpe']['base'])
Ole Troan57c3d662016-09-12 22:00:32 +0200172plugin_name_to_id(__name__, plugins['vpe']['name_to_id_table'], plugins['vpe']['base'])