--- /dev/null
+# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+ Runtime configuration manager.
+"""
+import logging
+
+from ryu.services.protocols.bgp.api.base import register
+from ryu.services.protocols.bgp.api.base import RegisterWithArgChecks
+from ryu.services.protocols.bgp.api.base import FLOWSPEC_FAMILY
+from ryu.services.protocols.bgp.api.base import FLOWSPEC_RULES
+from ryu.services.protocols.bgp.api.base import FLOWSPEC_ACTIONS
+from ryu.services.protocols.bgp.core_manager import CORE_MANAGER
+from ryu.services.protocols.bgp.rtconf.base import ConfWithId
+from ryu.services.protocols.bgp.rtconf.base import RuntimeConfigError
+from ryu.services.protocols.bgp.rtconf import neighbors
+from ryu.services.protocols.bgp.rtconf.neighbors import NeighborConf
+from ryu.services.protocols.bgp.rtconf.vrfs import ROUTE_DISTINGUISHER
+from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF
+from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4
+from ryu.services.protocols.bgp.rtconf.vrfs import VrfConf
+from ryu.services.protocols.bgp import constants as const
+
+LOG = logging.getLogger('bgpspeaker.api.rtconf')
+
+
+# =============================================================================
+# Neighbor configuration related APIs
+# =============================================================================
+
+
+def _get_neighbor_conf(neigh_ip_address):
+ """Returns neighbor configuration for given neighbor ip address.
+
+ Raises exception if no neighbor with `neigh_ip_address` exists.
+ """
+ neigh_conf = \
+ CORE_MANAGER.neighbors_conf.get_neighbor_conf(neigh_ip_address)
+ if not neigh_conf:
+ raise RuntimeConfigError(desc='No Neighbor configuration with IP'
+ ' address %s' % neigh_ip_address)
+ assert isinstance(neigh_conf, NeighborConf)
+ return neigh_conf
+
+
+@register(name='neighbor.create')
+def create_neighbor(**kwargs):
+ neigh_conf = NeighborConf(**kwargs)
+ CORE_MANAGER.neighbors_conf.add_neighbor_conf(neigh_conf)
+ return True
+
+
+@RegisterWithArgChecks(name='neighbor.update_enabled',
+ req_args=[neighbors.IP_ADDRESS, neighbors.ENABLED])
+def update_neighbor_enabled(neigh_ip_address, enabled):
+ neigh_conf = _get_neighbor_conf(neigh_ip_address)
+ neigh_conf.enabled = enabled
+ return True
+
+
+@RegisterWithArgChecks(name='neighbor.update',
+ req_args=[neighbors.IP_ADDRESS, neighbors.CHANGES])
+def update_neighbor(neigh_ip_address, changes):
+ rets = []
+ for k, v in changes.items():
+ if k == neighbors.MULTI_EXIT_DISC:
+ rets.append(_update_med(neigh_ip_address, v))
+
+ if k == neighbors.ENABLED:
+ rets.append(update_neighbor_enabled(neigh_ip_address, v))
+
+ if k == neighbors.CONNECT_MODE:
+ rets.append(_update_connect_mode(neigh_ip_address, v))
+
+ return all(rets)
+
+
+def _update_med(neigh_ip_address, value):
+ neigh_conf = _get_neighbor_conf(neigh_ip_address)
+ neigh_conf.multi_exit_disc = value
+ LOG.info('MED value for neigh: %s updated to %s', neigh_conf, value)
+ return True
+
+
+def _update_connect_mode(neigh_ip_address, value):
+ neigh_conf = _get_neighbor_conf(neigh_ip_address)
+ neigh_conf.connect_mode = value
+ return True
+
+
+@RegisterWithArgChecks(name='neighbor.delete',
+ req_args=[neighbors.IP_ADDRESS])
+def delete_neighbor(neigh_ip_address):
+ neigh_conf = _get_neighbor_conf(neigh_ip_address)
+ if neigh_conf:
+ neigh_conf.enabled = False
+ CORE_MANAGER.neighbors_conf.remove_neighbor_conf(neigh_ip_address)
+ return True
+ return False
+
+
+@RegisterWithArgChecks(name='neighbor.get',
+ req_args=[neighbors.IP_ADDRESS])
+def get_neighbor_conf(neigh_ip_address):
+ """Returns a neighbor configuration for given ip address if exists."""
+ neigh_conf = _get_neighbor_conf(neigh_ip_address)
+ return neigh_conf.settings
+
+
+@register(name='neighbors.get')
+def get_neighbors_conf():
+ return CORE_MANAGER.neighbors_conf.settings
+
+
+@RegisterWithArgChecks(name='neighbor.in_filter.get',
+ req_args=[neighbors.IP_ADDRESS])
+def get_neighbor_in_filter(neigh_ip_address):
+ """Returns a neighbor in_filter for given ip address if exists."""
+ core = CORE_MANAGER.get_core_service()
+ peer = core.peer_manager.get_by_addr(neigh_ip_address)
+ return peer.in_filters
+
+
+@RegisterWithArgChecks(name='neighbor.in_filter.set',
+ req_args=[neighbors.IP_ADDRESS, neighbors.IN_FILTER])
+def set_neighbor_in_filter(neigh_ip_address, filters):
+ """Returns a neighbor in_filter for given ip address if exists."""
+ core = CORE_MANAGER.get_core_service()
+ peer = core.peer_manager.get_by_addr(neigh_ip_address)
+ peer.in_filters = filters
+ return True
+
+
+@RegisterWithArgChecks(name='neighbor.out_filter.get',
+ req_args=[neighbors.IP_ADDRESS])
+def get_neighbor_out_filter(neigh_ip_address):
+ """Returns a neighbor out_filter for given ip address if exists."""
+ core = CORE_MANAGER.get_core_service()
+ ret = core.peer_manager.get_by_addr(neigh_ip_address).out_filters
+ return ret
+
+
+@RegisterWithArgChecks(name='neighbor.out_filter.set',
+ req_args=[neighbors.IP_ADDRESS, neighbors.OUT_FILTER])
+def set_neighbor_out_filter(neigh_ip_address, filters):
+ """Sets the out_filter of a neighbor."""
+ core = CORE_MANAGER.get_core_service()
+ peer = core.peer_manager.get_by_addr(neigh_ip_address)
+ peer.out_filters = filters
+ return True
+
+
+@RegisterWithArgChecks(name='neighbor.attribute_map.set',
+ req_args=[neighbors.IP_ADDRESS,
+ neighbors.ATTRIBUTE_MAP],
+ opt_args=[ROUTE_DISTINGUISHER, VRF_RF])
+def set_neighbor_attribute_map(neigh_ip_address, at_maps,
+ route_dist=None, route_family=VRF_RF_IPV4):
+ """set attribute_maps to the neighbor."""
+ core = CORE_MANAGER.get_core_service()
+ peer = core.peer_manager.get_by_addr(neigh_ip_address)
+
+ at_maps_key = const.ATTR_MAPS_LABEL_DEFAULT
+ at_maps_dict = {}
+
+ if route_dist is not None:
+ vrf_conf =\
+ CORE_MANAGER.vrfs_conf.get_vrf_conf(route_dist, route_family)
+ if vrf_conf:
+ at_maps_key = ':'.join([route_dist, route_family])
+ else:
+ raise RuntimeConfigError(desc='No VrfConf with rd %s' %
+ route_dist)
+
+ at_maps_dict[const.ATTR_MAPS_LABEL_KEY] = at_maps_key
+ at_maps_dict[const.ATTR_MAPS_VALUE] = at_maps
+ peer.attribute_maps = at_maps_dict
+
+ return True
+
+
+@RegisterWithArgChecks(name='neighbor.attribute_map.get',
+ req_args=[neighbors.IP_ADDRESS],
+ opt_args=[ROUTE_DISTINGUISHER, VRF_RF])
+def get_neighbor_attribute_map(neigh_ip_address, route_dist=None,
+ route_family=VRF_RF_IPV4):
+ """Returns a neighbor attribute_map for given ip address if exists."""
+ core = CORE_MANAGER.get_core_service()
+ peer = core.peer_manager.get_by_addr(neigh_ip_address)
+ at_maps_key = const.ATTR_MAPS_LABEL_DEFAULT
+
+ if route_dist is not None:
+ at_maps_key = ':'.join([route_dist, route_family])
+ at_maps = peer.attribute_maps.get(at_maps_key)
+ if at_maps:
+ return at_maps.get(const.ATTR_MAPS_ORG_KEY)
+ else:
+ return []
+
+# =============================================================================
+# VRF configuration related APIs
+# =============================================================================
+
+
+@register(name='vrf.create')
+def create_vrf(**kwargs):
+ vrf_conf = VrfConf(**kwargs)
+ CORE_MANAGER.vrfs_conf.add_vrf_conf(vrf_conf)
+ return True
+
+
+@register(name='vrf.update')
+def update_vrf(**kwargs):
+ route_dist = kwargs.get(ROUTE_DISTINGUISHER)
+ vrf_id = kwargs.get(ConfWithId.ID)
+ vrf_rf = kwargs.get(VRF_RF)
+ vrf_conf = CORE_MANAGER.vrfs_conf.get_vrf_conf(
+ route_dist, vrf_rf, vrf_id=vrf_id
+ )
+
+ # If we do not have a VrfConf with given id, we create one.
+ if not vrf_conf:
+ create_vrf(**kwargs)
+ else:
+ vrf_conf.update(**kwargs)
+ return True
+
+
+@RegisterWithArgChecks(name='vrf.delete', req_args=[ROUTE_DISTINGUISHER])
+def delete_vrf(route_dist):
+ vrf_conf = CORE_MANAGER.vrfs_conf.remove_vrf_conf(route_dist)
+ if vrf_conf:
+ return True
+
+ return False
+
+
+@RegisterWithArgChecks(
+ name='vrf.get',
+ req_args=[ROUTE_DISTINGUISHER],
+ opt_args=[VRF_RF])
+def get_vrf(route_dist, route_family=VRF_RF_IPV4):
+ vrf_conf = CORE_MANAGER.vrfs_conf.get_vrf_conf(
+ route_dist, vrf_rf=route_family
+ )
+ if not vrf_conf:
+ raise RuntimeConfigError(desc='No VrfConf with vpn id %s' %
+ route_dist)
+ return vrf_conf.settings
+
+
+@register(name='vrfs.get')
+def get_vrfs_conf():
+ vrfs_conf = CORE_MANAGER.vrfs_conf
+ return vrfs_conf.settings
+
+# =============================================================================
+# network configuration related APIs
+# =============================================================================
+
+
+@register(name='network.add')
+def add_network(prefix, next_hop=None):
+ tm = CORE_MANAGER.get_core_service().table_manager
+ tm.update_global_table(prefix, next_hop)
+ return True
+
+
+@register(name='network.del')
+def del_network(prefix):
+ tm = CORE_MANAGER.get_core_service().table_manager
+ tm.update_global_table(prefix, is_withdraw=True)
+ return True
+
+# =============================================================================
+# BMP configuration related APIs
+# =============================================================================
+
+
+@register(name='bmp.start')
+def bmp_start(host, port):
+ core = CORE_MANAGER.get_core_service()
+ return core.start_bmp(host, port)
+
+
+@register(name='bmp.stop')
+def bmp_stop(host, port):
+ core = CORE_MANAGER.get_core_service()
+ return core.stop_bmp(host, port)
+
+
+# =============================================================================
+# BGP Flow Specification Routes related APIs
+# =============================================================================
+
+@RegisterWithArgChecks(
+ name='flowspec.add',
+ req_args=[FLOWSPEC_FAMILY, FLOWSPEC_RULES],
+ opt_args=[FLOWSPEC_ACTIONS])
+def add_flowspec(flowspec_family, rules, **kwargs):
+ tm = CORE_MANAGER.get_core_service().table_manager
+ tm.update_flowspec_global_table(flowspec_family, rules, **kwargs)
+ return True
+
+
+@RegisterWithArgChecks(
+ name='flowspec.del',
+ req_args=[FLOWSPEC_FAMILY, FLOWSPEC_RULES])
+def del_flowspec(flowspec_family, rules):
+ tm = CORE_MANAGER.get_core_service().table_manager
+ tm.update_flowspec_global_table(flowspec_family, rules, is_withdraw=True)
+ return True