-
Notifications
You must be signed in to change notification settings - Fork 11
/
vppapi.py
144 lines (116 loc) · 4.35 KB
/
vppapi.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""
The functions in this file interact with the VPP API to retrieve certain
interface metadata.
"""
from vpp_papi import VPPApiClient, VPPApiJSONFiles
import os
import fnmatch
import logging
import socket
class NullHandler(logging.Handler):
def emit(self, record):
pass
logger = logging.getLogger("agentx.vppapi")
logger.addHandler(NullHandler())
class VPPApi:
def __init__(self, address="/run/vpp/api.sock", clientname="vppapi-client"):
self.address = address
self.connected = False
self.clientname = clientname
self.vpp = None
self.iface_dict = None
self.lcp_dict = None
def _sw_interface_event(self, event):
# NOTE(pim): this callback runs in a background thread, so we just clear the
# cached interfaces and LCPs here, subsequent call to get_ifaces() or get_lcp()
# will refresh them in the main thread.
logger.info(f"Clearing iface and LCP cache due to interface event")
self.iface_dict = None
self.lcp_dict = None
def _event_callback(self, msg_type_name, msg_type):
logger.debug(f"Received callback: {msg_type_name} => {msg_type}")
if msg_type_name == "sw_interface_event":
self._sw_interface_event(msg_type)
else:
logger.warning(f"Ignoring unkonwn event: {msg_type_name} => {msg_type}")
def connect(self):
if self.connected:
return True
vpp_json_dir = VPPApiJSONFiles.find_api_dir([])
vpp_jsonfiles = VPPApiJSONFiles.find_api_files(api_dir=vpp_json_dir)
if not vpp_jsonfiles:
logger.error("no json api files found")
return False
self.vpp = VPPApiClient(apifiles=vpp_jsonfiles, server_address=self.address)
self.vpp.register_event_callback(self._event_callback)
try:
logger.info("Connecting to VPP")
self.vpp.connect(self.clientname)
except:
return False
v = self.vpp.api.show_version()
logger.info("VPP version is %s" % v.version)
logger.info("Enabling VPP API interface events")
r = self.vpp.api.want_interface_events(enable_disable=True)
if r.retval != 0:
logger.error("Could not enable VPP API interface events, disconnecting")
self.disconnect()
return False
self.connected = True
return True
def disconnect(self):
if not self.connected:
return True
self.vpp.disconnect()
self.iface_dict = None
self.lcp_dict = None
self.connected = False
return True
def get_ifaces(self):
ret = {}
if not self.connected and not self.connect():
logger.warning("Can't connect to VPP API")
return ret
if type(self.iface_dict) is dict:
logger.debug("Returning cached interfaces")
return self.iface_dict
ret = {}
try:
logger.info("Requesting interfaces from VPP API")
iface_list = self.vpp.api.sw_interface_dump()
except Exception as e:
logger.error("VPP API communication error, disconnecting", e)
self.disconnect()
return ret
if not iface_list:
logger.error("Can't get interface list, disconnecting")
self.disconnect()
return ret
for iface in iface_list:
ret[iface.interface_name] = iface
self.iface_dict = ret
logger.debug(f"Caching interfaces: {ret}")
return self.iface_dict
def get_lcp(self):
ret = {}
if not self.connected and not self.connect():
logger.warning("Can't connect to VPP API")
return ret
if type(self.lcp_dict) is dict:
logger.debug("Returning cached LCPs")
return self.lcp_dict
try:
logger.info("Requesting LCPs from VPP API")
lcp_list = self.vpp.api.lcp_itf_pair_get()
except Exception as e:
logger.error("VPP communication error, disconnecting", e)
self.disconnect()
return ret
if not lcp_list:
logger.error("Can't get LCP list")
return ret
for lcp in lcp_list[1]:
ret[lcp.host_if_name] = lcp
self.lcp_dict = ret
logger.debug(f"Caching LCPs: {ret}")
return self.lcp_dict