--- /dev/null
+import logging
+import traceback
+
+from ryu.lib.packet.bgp import RouteFamily
+from ryu.lib.packet.bgp import RF_IPv4_UC
+from ryu.lib.packet.bgp import RF_IPv6_UC
+from ryu.lib.packet.bgp import RF_IPv4_VPN
+from ryu.lib.packet.bgp import RF_IPv6_VPN
+from ryu.lib.packet.bgp import RF_L2_EVPN
+from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC
+from ryu.lib.packet.bgp import RF_IPv6_FLOWSPEC
+from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC
+from ryu.lib.packet.bgp import RF_VPNv6_FLOWSPEC
+from ryu.lib.packet.bgp import RF_L2VPN_FLOWSPEC
+from ryu.lib.packet.bgp import RF_RTC_UC
+from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
+from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
+from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC
+from ryu.lib.packet.bgp import BGP_ATTR_TYPE_LOCAL_PREF
+from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_IGP
+from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_EGP
+from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_INCOMPLETE
+
+from ryu.services.protocols.bgp.base import add_bgp_error_metadata
+from ryu.services.protocols.bgp.base import BGPSException
+from ryu.services.protocols.bgp.base import SUPPORTED_GLOBAL_RF
+from ryu.services.protocols.bgp.core_manager import CORE_MANAGER
+
+
+LOG = logging.getLogger('bgpspeaker.operator.internal_api')
+
+INTERNAL_API_ERROR = 100
+INTERNAL_API_SUB_ERROR = 101
+
+
+class InternalApi(object):
+
+ def __init__(self, log_handler=None):
+ self.log_handler = log_handler
+
+ def count_all_vrf_routes(self):
+ vrf_tables = self._get_vrf_tables()
+ ret = {}
+ for key in vrf_tables.keys():
+ vrf_name, vrf_rf = key
+ ret.update(self.count_single_vrf_routes(vrf_name, vrf_rf))
+ return ret
+
+ def count_single_vrf_routes(self, vrf_name, vrf_rf):
+ vrf = self._get_vrf_tables().get((vrf_name, vrf_rf))
+ if vrf is None:
+ raise WrongParamError('wrong vpn key %s' % str((vrf_name, vrf_rf)))
+ vrf_name = vrf_name.encode('ascii', 'ignore')
+
+ route_count = \
+ len([d for d in vrf.values() if d.best_path])
+ return {str((vrf_name, vrf_rf)): route_count}
+
+ def get_vrfs_conf(self):
+ return CORE_MANAGER.vrfs_conf.vrfs_by_rd_rf_id
+
+ def get_all_vrf_routes(self):
+ vrfs = self._get_vrf_tables()
+ ret = {}
+ for (vrf_id, vrf_rf), table in sorted(vrfs.items()):
+ ret[str((vrf_id, vrf_rf))] = self._get_single_vrf_routes(table)
+ return ret
+
+ def get_single_vrf_routes(self, vrf_id, vrf_rf):
+ vrf = self._get_vrf_table(vrf_id, vrf_rf)
+ if not vrf:
+ raise WrongParamError('wrong vpn name %s' % str((vrf_id, vrf_rf)))
+ return [self._dst_to_dict(d) for d in vrf.values()]
+
+ def _get_single_vrf_routes(self, vrf_table):
+ return [self._dst_to_dict(d) for d in vrf_table.values()]
+
+ def _get_vrf_table(self, vrf_name, vrf_rf):
+ return CORE_MANAGER.get_core_service()\
+ .table_manager.get_vrf_table(vrf_name, vrf_rf)
+
+ def _get_vrf_tables(self):
+ return CORE_MANAGER.get_core_service().table_manager.get_vrf_tables()
+
+ def get_single_rib_routes(self, addr_family):
+ rfs = {
+ 'ipv4': RF_IPv4_UC,
+ 'ipv6': RF_IPv6_UC,
+ 'vpnv4': RF_IPv4_VPN,
+ 'vpnv6': RF_IPv6_VPN,
+ 'evpn': RF_L2_EVPN,
+ 'ipv4fs': RF_IPv4_FLOWSPEC,
+ 'ipv6fs': RF_IPv6_FLOWSPEC,
+ 'vpnv4fs': RF_VPNv4_FLOWSPEC,
+ 'vpnv6fs': RF_VPNv6_FLOWSPEC,
+ 'l2vpnfs': RF_L2VPN_FLOWSPEC,
+ 'rtfilter': RF_RTC_UC
+ }
+ if addr_family not in rfs:
+ raise WrongParamError('Unknown or unsupported family: %s' %
+ addr_family)
+
+ rf = rfs.get(addr_family)
+ table_manager = self.get_core_service().table_manager
+ gtable = table_manager.get_global_table_by_route_family(rf)
+ if gtable is not None:
+ return [self._dst_to_dict(dst)
+ for dst in sorted(gtable.values())]
+ else:
+ return []
+
+ def _dst_to_dict(self, dst):
+ ret = {'paths': [],
+ 'prefix': dst.nlri_str}
+
+ def _path_to_dict(dst, path):
+
+ path_seg_list = path.get_pattr(BGP_ATTR_TYPE_AS_PATH).path_seg_list
+
+ if isinstance(path_seg_list, list):
+ aspath = []
+ for as_path_seg in path_seg_list:
+ for as_num in as_path_seg:
+ aspath.append(as_num)
+ else:
+ aspath = ''
+
+ origin = path.get_pattr(BGP_ATTR_TYPE_ORIGIN)
+ origin = origin.value if origin else None
+
+ if origin == BGP_ATTR_ORIGIN_IGP:
+ origin = 'i'
+ elif origin == BGP_ATTR_ORIGIN_EGP:
+ origin = 'e'
+ elif origin == BGP_ATTR_ORIGIN_INCOMPLETE:
+ origin = '?'
+
+ nexthop = path.nexthop
+ # Get the MED path attribute
+ med = path.get_pattr(BGP_ATTR_TYPE_MULTI_EXIT_DISC)
+ med = med.value if med else ''
+ # Get best path reason
+ bpr = dst.best_path_reason if path == dst.best_path else ''
+
+ # Get local preference
+ localpref = path.get_pattr(BGP_ATTR_TYPE_LOCAL_PREF)
+ localpref = localpref.value if localpref else ''
+
+ if hasattr(path.nlri, 'label_list'):
+ labels = path.nlri.label_list
+ else:
+ labels = None
+
+ return {'best': (path == dst.best_path),
+ 'bpr': bpr,
+ 'prefix': path.nlri_str,
+ 'labels': labels,
+ 'nexthop': nexthop,
+ 'metric': med,
+ 'aspath': aspath,
+ 'origin': origin,
+ 'localpref': localpref}
+
+ for path in dst.known_path_list:
+ ret['paths'].append(_path_to_dict(dst, path))
+
+ return ret
+
+ def check_logging(self):
+ return self.log_handler and self._has_log_handler(self.log_handler)
+
+ def check_logging_level(self):
+ return logging.getLevelName(self.log_handler.level)
+
+ def _has_log_handler(self, log_handler):
+ if log_handler in logging.getLogger('bgpspeaker').handlers:
+ return True
+ return False
+
+ def route_refresh(self, peer_ip=None, afi=None, safi=None):
+ if not peer_ip:
+ peer_ip = 'all'
+
+ try:
+ route_families = []
+ if afi is None and safi is None:
+ route_families.extend(SUPPORTED_GLOBAL_RF)
+ else:
+ route_family = RouteFamily(afi, safi)
+ if route_family not in SUPPORTED_GLOBAL_RF:
+ raise WrongParamError('Not supported address-family'
+ ' %s, %s' % (afi, safi))
+ route_families.append(route_family)
+
+ pm = CORE_MANAGER.get_core_service().peer_manager
+ pm.make_route_refresh_request(peer_ip, *route_families)
+ except Exception as e:
+ LOG.error(traceback.format_exc())
+ raise WrongParamError(str(e))
+ return None
+
+ def get_core_service(self):
+ return CORE_MANAGER.get_core_service()
+
+
+@add_bgp_error_metadata(code=INTERNAL_API_ERROR,
+ sub_code=INTERNAL_API_SUB_ERROR,
+ def_desc='Unknown internal api exception.')
+class WrongParamError(BGPSException):
+ pass