backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / bgp / rtconf / common.py
diff --git a/ryu/build/lib.linux-armv7l-2.7/ryu/services/protocols/bgp/rtconf/common.py b/ryu/build/lib.linux-armv7l-2.7/ryu/services/protocols/bgp/rtconf/common.py
new file mode 100644 (file)
index 0000000..9f6c0a1
--- /dev/null
@@ -0,0 +1,415 @@
+# 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 that applies to all bgp sessions, i.e. global settings.
+"""
+import logging
+import numbers
+
+from ryu.lib import ip
+
+from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4
+from ryu.services.protocols.bgp.utils.validation import is_valid_asn
+
+from ryu.services.protocols.bgp import rtconf
+from ryu.services.protocols.bgp.rtconf.base import BaseConf
+from ryu.services.protocols.bgp.rtconf.base import BaseConfListener
+from ryu.services.protocols.bgp.rtconf.base import compute_optional_conf
+from ryu.services.protocols.bgp.rtconf.base import ConfigTypeError
+from ryu.services.protocols.bgp.rtconf.base import ConfigValueError
+from ryu.services.protocols.bgp.rtconf.base import MissingRequiredConf
+from ryu.services.protocols.bgp.rtconf.base import validate
+
+LOG = logging.getLogger('bgpspeaker.rtconf.common')
+
+
+# Global configuration settings.
+LOCAL_AS = 'local_as'
+ROUTER_ID = 'router_id'
+CLUSTER_ID = 'cluster_id'
+LABEL_RANGE = 'label_range'
+LABEL_RANGE_MAX = 'max'
+LABEL_RANGE_MIN = 'min'
+LOCAL_PREF = 'local_pref'
+
+# Similar to Cisco command 'allowas-in'. Allows the local ASN in the path.
+# Facilitates auto rd, auto rt import/export
+# ("rd auto/route-target both auto") and simplified spine/leaf architectures,
+# sharing an ASN between e.g. leafs.
+ALLOW_LOCAL_AS_IN_COUNT = 'allow_local_as_in_count'
+
+# Configuration that can be set at global level as well as per context
+# (session/vrf) level
+# Nested configuration override global or higher level configuration as they
+# are more granular.
+# TODO(apgw-dev) Nested configuration overriding higher level configuration is
+# currently low priority
+
+# Similar to Cisco command 'bgp refresh stalepath-time'. To cause the router to
+# remove stale routes from the BGP table even if the router does not receive a
+# Route-Refresh EOR message The bgp refresh stalepath-time command is not
+# needed under normal circumstances.
+# TODO(PH): Support this feature (currently low priority)
+REFRESH_STALEPATH_TIME = 'refresh_stalepath_time'
+
+# Similar to Cisco command 'bgp refresh max-eor-time'. The bgp refresh max-eor-
+# time command is not needed under normal  circumstances. You might configure
+# the bgp refresh max-eor-time command in the event of continuous route
+# flapping, when the router is unable to generate a Route- Refresh EOR message,
+# in which case a Route-Refresh EOR is generated after the timer expires.
+# TODO(PH): Support this feature (currently low priority)
+REFRESH_MAX_EOR_TIME = 'refresh_max_eor_time'
+
+BGP_CONN_RETRY_TIME = 'bgp_conn_retry_time'
+BGP_SERVER_HOSTS = 'bgp_server_hosts'
+BGP_SERVER_PORT = 'bgp_server_port'
+TCP_CONN_TIMEOUT = 'tcp_conn_timeout'
+MAX_PATH_EXT_RTFILTER_ALL = 'maximum_paths_external_rtfilter_all'
+
+
+# Valid default values of some settings.
+DEFAULT_LABEL_RANGE = (100, 100000)
+DEFAULT_REFRESH_STALEPATH_TIME = 0
+DEFAULT_REFRESH_MAX_EOR_TIME = 0
+DEFAULT_BGP_SERVER_HOSTS = ('0.0.0.0', '::')
+DEFAULT_BGP_SERVER_PORT = 179
+DEFAULT_TCP_CONN_TIMEOUT = 30
+DEFAULT_BGP_CONN_RETRY_TIME = 30
+DEFAULT_MED = 0
+DEFAULT_MAX_PATH_EXT_RTFILTER_ALL = True
+DEFAULT_LOCAL_PREF = 100
+
+
+@validate(name=ALLOW_LOCAL_AS_IN_COUNT)
+def validate_allow_local_as_in_count(count):
+    if not isinstance(count, numbers.Integral):
+        raise ConfigTypeError(desc=('Configuration value for %s has to be '
+                                    'integral type' % ALLOW_LOCAL_AS_IN_COUNT))
+    if count < 0:
+        raise ConfigValueError(desc='Invalid local AS count %s' % count)
+
+    return count
+
+
+@validate(name=LOCAL_AS)
+def validate_local_as(asn):
+    if asn is None:
+        raise MissingRequiredConf(conf_name=LOCAL_AS)
+
+    if not is_valid_asn(asn):
+        raise ConfigValueError(desc='Invalid local_as configuration value: %s'
+                               % asn)
+    return asn
+
+
+@validate(name=ROUTER_ID)
+def validate_router_id(router_id):
+    if not router_id:
+        raise MissingRequiredConf(conf_name=ROUTER_ID)
+
+    if not isinstance(router_id, str):
+        raise ConfigTypeError(conf_name=ROUTER_ID)
+    if not is_valid_ipv4(router_id):
+        raise ConfigValueError(desc='Invalid router id %s' % router_id)
+
+    return router_id
+
+
+@validate(name=CLUSTER_ID)
+def validate_router_id(cluster_id):
+    if not isinstance(cluster_id, str):
+        raise ConfigTypeError(conf_name=CLUSTER_ID)
+    if not is_valid_ipv4(cluster_id):
+        raise ConfigValueError(desc='Invalid cluster id %s' % cluster_id)
+
+    return cluster_id
+
+
+@validate(name=REFRESH_STALEPATH_TIME)
+def validate_refresh_stalepath_time(rst):
+    if not isinstance(rst, numbers.Integral):
+        raise ConfigTypeError(desc=('Configuration value for %s has to be '
+                                    'integral type' % REFRESH_STALEPATH_TIME))
+    if rst < 0:
+        raise ConfigValueError(desc='Invalid refresh stalepath time %s' % rst)
+
+    return rst
+
+
+@validate(name=REFRESH_MAX_EOR_TIME)
+def validate_refresh_max_eor_time(rmet):
+    if not isinstance(rmet, numbers.Integral):
+        raise ConfigTypeError(desc=('Configuration value for %s has to be of '
+                                    'integral type ' % REFRESH_MAX_EOR_TIME))
+    if rmet < 0:
+        raise ConfigValueError(desc='Invalid refresh stalepath time %s' % rmet)
+
+    return rmet
+
+
+@validate(name=LABEL_RANGE)
+def validate_label_range(label_range):
+    min_label, max_label = label_range
+    if (not min_label or
+            not max_label or
+            not isinstance(min_label, numbers.Integral) or
+            not isinstance(max_label, numbers.Integral) or min_label < 17 or
+            min_label >= max_label):
+        raise ConfigValueError(desc=('Invalid label_range configuration value:'
+                                     ' (%s).' % label_range))
+
+    return label_range
+
+
+@validate(name=BGP_SERVER_HOSTS)
+def validate_bgp_server_hosts(hosts):
+    for host in hosts:
+        if not ip.valid_ipv4(host) and not ip.valid_ipv6(host):
+            raise ConfigTypeError(desc=('Invalid bgp sever hosts '
+                                        'configuration value %s' % hosts))
+
+    return hosts
+
+
+@validate(name=BGP_SERVER_PORT)
+def validate_bgp_server_port(server_port):
+    if not isinstance(server_port, numbers.Integral):
+        raise ConfigTypeError(desc=('Invalid bgp sever port configuration '
+                                    'value %s' % server_port))
+    if server_port < 0 or server_port > 65535:
+        raise ConfigValueError(desc='Invalid server port %s' % server_port)
+
+    return server_port
+
+
+@validate(name=TCP_CONN_TIMEOUT)
+def validate_tcp_conn_timeout(tcp_conn_timeout):
+    # TODO(apgw-dev) made-up some valid values for this settings, check if we
+    # have a standard value in any routers
+    if not isinstance(tcp_conn_timeout, numbers.Integral):
+        raise ConfigTypeError(desc=('Invalid tcp connection timeout '
+                                    'configuration value %s' %
+                                    tcp_conn_timeout))
+
+    if tcp_conn_timeout < 10:
+        raise ConfigValueError(desc=('Invalid tcp connection timeout'
+                                     ' configuration value %s' %
+                                     tcp_conn_timeout))
+
+    return tcp_conn_timeout
+
+
+@validate(name=BGP_CONN_RETRY_TIME)
+def validate_bgp_conn_retry_time(bgp_conn_retry_time):
+    if not isinstance(bgp_conn_retry_time, numbers.Integral):
+        raise ConfigTypeError(desc=('Invalid bgp conn. retry time '
+                                    'configuration value %s' %
+                                    bgp_conn_retry_time))
+
+    if bgp_conn_retry_time < 10:
+        raise ConfigValueError(desc=('Invalid bgp connection retry time'
+                                     ' configuration value %s' %
+                                     bgp_conn_retry_time))
+    return bgp_conn_retry_time
+
+
+@validate(name=MAX_PATH_EXT_RTFILTER_ALL)
+def validate_max_path_ext_rtfilter_all(max_path_ext_rtfilter_all):
+    if not isinstance(max_path_ext_rtfilter_all, bool):
+        raise ConfigTypeError(desc=('Invalid max_path_ext_rtfilter_all'
+                                    ' configuration value %s' %
+                                    max_path_ext_rtfilter_all))
+    return max_path_ext_rtfilter_all
+
+
+@validate(name=LOCAL_PREF)
+def validate_local_pref(local_pref):
+    if not isinstance(local_pref, numbers.Integral):
+        raise ConfigTypeError(desc=('Invalid local_pref'
+                                    ' configuration value %s' %
+                                    local_pref))
+    return local_pref
+
+
+class CommonConf(BaseConf):
+    """Encapsulates configurations applicable to all peer sessions.
+
+    Currently if any of these configurations change, it is assumed that current
+    active peer session will be bought down and restarted.
+    """
+    CONF_CHANGED_EVT = 1
+
+    VALID_EVT = frozenset([CONF_CHANGED_EVT])
+
+    REQUIRED_SETTINGS = frozenset([ROUTER_ID, LOCAL_AS])
+
+    OPTIONAL_SETTINGS = frozenset([REFRESH_STALEPATH_TIME,
+                                   REFRESH_MAX_EOR_TIME, LABEL_RANGE,
+                                   BGP_SERVER_HOSTS, BGP_SERVER_PORT,
+                                   TCP_CONN_TIMEOUT,
+                                   BGP_CONN_RETRY_TIME,
+                                   MAX_PATH_EXT_RTFILTER_ALL,
+                                   ALLOW_LOCAL_AS_IN_COUNT,
+                                   CLUSTER_ID,
+                                   LOCAL_PREF])
+
+    def __init__(self, **kwargs):
+        super(CommonConf, self).__init__(**kwargs)
+
+    def _init_opt_settings(self, **kwargs):
+        super(CommonConf, self)._init_opt_settings(**kwargs)
+        self._settings[ALLOW_LOCAL_AS_IN_COUNT] = compute_optional_conf(
+            ALLOW_LOCAL_AS_IN_COUNT, 0, **kwargs)
+        self._settings[LABEL_RANGE] = compute_optional_conf(
+            LABEL_RANGE, DEFAULT_LABEL_RANGE, **kwargs)
+        self._settings[REFRESH_STALEPATH_TIME] = compute_optional_conf(
+            REFRESH_STALEPATH_TIME, DEFAULT_REFRESH_STALEPATH_TIME, **kwargs)
+        self._settings[REFRESH_MAX_EOR_TIME] = compute_optional_conf(
+            REFRESH_MAX_EOR_TIME, DEFAULT_REFRESH_MAX_EOR_TIME, **kwargs)
+        self._settings[BGP_SERVER_HOSTS] = compute_optional_conf(
+            BGP_SERVER_HOSTS, DEFAULT_BGP_SERVER_HOSTS, **kwargs)
+        self._settings[BGP_SERVER_PORT] = compute_optional_conf(
+            BGP_SERVER_PORT, DEFAULT_BGP_SERVER_PORT, **kwargs)
+        self._settings[TCP_CONN_TIMEOUT] = compute_optional_conf(
+            TCP_CONN_TIMEOUT, DEFAULT_TCP_CONN_TIMEOUT, **kwargs)
+        self._settings[BGP_CONN_RETRY_TIME] = compute_optional_conf(
+            BGP_CONN_RETRY_TIME, DEFAULT_BGP_CONN_RETRY_TIME, **kwargs)
+        self._settings[MAX_PATH_EXT_RTFILTER_ALL] = compute_optional_conf(
+            MAX_PATH_EXT_RTFILTER_ALL, DEFAULT_MAX_PATH_EXT_RTFILTER_ALL,
+            **kwargs)
+        self._settings[CLUSTER_ID] = compute_optional_conf(
+            CLUSTER_ID, kwargs[ROUTER_ID], **kwargs)
+        self._settings[LOCAL_PREF] = compute_optional_conf(
+            LOCAL_PREF, DEFAULT_LOCAL_PREF, **kwargs)
+
+    # =========================================================================
+    # Required attributes
+    # =========================================================================
+
+    @property
+    def local_as(self):
+        return self._settings[LOCAL_AS]
+
+    @property
+    def router_id(self):
+        return self._settings[ROUTER_ID]
+
+    # =========================================================================
+    # Optional attributes with valid defaults.
+    # =========================================================================
+    @property
+    def cluster_id(self):
+        return self._settings[CLUSTER_ID]
+
+    @property
+    def allow_local_as_in_count(self):
+        return self._settings[ALLOW_LOCAL_AS_IN_COUNT]
+
+    @property
+    def bgp_conn_retry_time(self):
+        return self._settings[BGP_CONN_RETRY_TIME]
+
+    @property
+    def tcp_conn_timeout(self):
+        return self._settings[TCP_CONN_TIMEOUT]
+
+    @property
+    def refresh_stalepath_time(self):
+        return self._settings[REFRESH_STALEPATH_TIME]
+
+    @property
+    def refresh_max_eor_time(self):
+        return self._settings[REFRESH_MAX_EOR_TIME]
+
+    @property
+    def label_range(self):
+        return self._settings[LABEL_RANGE]
+
+    @property
+    def bgp_server_hosts(self):
+        return self._settings[BGP_SERVER_HOSTS]
+
+    @property
+    def bgp_server_port(self):
+        return self._settings[BGP_SERVER_PORT]
+
+    @property
+    def max_path_ext_rtfilter_all(self):
+        return self._settings[MAX_PATH_EXT_RTFILTER_ALL]
+
+    @property
+    def local_pref(self):
+        return self._settings[LOCAL_PREF]
+
+    @classmethod
+    def get_opt_settings(self):
+        self_confs = super(CommonConf, self).get_opt_settings()
+        self_confs.update(CommonConf.OPTIONAL_SETTINGS)
+        return self_confs
+
+    @classmethod
+    def get_req_settings(self):
+        self_confs = super(CommonConf, self).get_req_settings()
+        self_confs.update(CommonConf.REQUIRED_SETTINGS)
+        return self_confs
+
+    @classmethod
+    def get_valid_evts(self):
+        self_valid_evts = super(CommonConf, self).get_valid_evts()
+        self_valid_evts.update(CommonConf.VALID_EVT)
+        return self_valid_evts
+
+    def update(self, **kwargs):
+        """Updates global configuration settings with given values.
+
+        First checks if given configuration values differ from current values.
+        If any of the configuration values changed, generates a change event.
+        Currently we generate change event for any configuration change.
+        Note: This method is idempotent.
+        """
+        # Update inherited configurations
+        super(CommonConf, self).update(**kwargs)
+        conf_changed = False
+
+        # Validate given configurations and check if value changed
+        for conf_name, conf_value in kwargs.items():
+            rtconf.base.get_validator(conf_name)(conf_value)
+            item1 = self._settings.get(conf_name, None)
+            item2 = kwargs.get(conf_name, None)
+
+            if item1 != item2:
+                conf_changed = True
+
+        # If any configuration changed, we update configuration value and
+        # notify listeners
+        if conf_changed:
+            for conf_name, conf_value in kwargs.items():
+                # Since all new values are already validated, we can use them
+                self._settings[conf_name] = conf_value
+
+            self._notify_listeners(CommonConf.CONF_CHANGED_EVT, self)
+
+
+class CommonConfListener(BaseConfListener):
+    """Base listener for various changes to common configurations."""
+
+    def __init__(self, global_conf):
+        super(CommonConfListener, self).__init__(global_conf)
+        global_conf.add_listener(CommonConf.CONF_CHANGED_EVT,
+                                 self.on_update_common_conf)
+
+    def on_update_common_conf(self, evt):
+        raise NotImplementedError('This method should be overridden.')