コード例 #1
0
ファイル: lpm.py プロジェクト: vmorokhx/sonic-mgmt
 def __init__(self, ipv4=True):
     self._ipv4 = ipv4
     self._prefix_set = set()
     self._subnet_tree = SubnetTree()
     # 0.0.0.0 is a non-routable meta-address that needs to be skipped
     self._boundaries = {
         ip_address(u'0.0.0.0'): 1
     } if ipv4 else {
         ip_address(u'::'): 1
     }
コード例 #2
0
    def __init__(self):

        """Create a BGP protocol.
        """
        self.fsm = None
        self.peer_id = None

        self.disconnected = False
        self._receive_buffer = b''
        self.fourbytesas = False
        self.add_path_ipv4_receive = False
        self.add_path_ipv4_send = False
        self.adj_rib_in = {k: {} for k in CONF.bgp.afi_safi}
        self.adj_rib_out = {k: {} for k in CONF.bgp.afi_safi}
        self.adj_rib_in_ipv4_tree = SubnetTree()

        # statistic
        self.msg_sent_stat = {
            'Opens': 0,
            'Notifications': 0,
            'Updates': 0,
            'Keepalives': 0,
            'RouteRefresh': 0
        }
        self.msg_recv_stat = {
            'Opens': 0,
            'Notifications': 0,
            'Updates': 0,
            'Keepalives': 0,
            'RouteRefresh': 0
        }
        self.send_version = {
            'ipv4': 0,
            'flowspec': 0,
            'sr_policy': 0,
            'mpls_vpn': 0
        }
        self.receive_version = {
            'ipv4': 0,
            'flowspec': 0,
            'sr_policy': 0,
            'mpls_vpn': 0
        }

        self.flowspec_send_dict = {}
        self.flowspec_receive_dict = {}
        self.sr_send_dict = {}
        self.sr_receive_dict = {}
        self.mpls_vpn_send_dict = {}
        self.mpls_vpn_receive_dict = {}
コード例 #3
0
ファイル: views_topology.py プロジェクト: yhyan/vns
def topology_permitted_sip_add(request, tid, topo):
    tn = 'vns/topology_add_permitted_sip.html'
    if request.method == 'POST':
        form = APSIPForm(request.POST)
        if form.is_valid():
            ip = str(form.cleaned_data['ip'])
            mask = int(form.cleaned_data['mask'])

            # build a tree of existing filters
            st = SubnetTree()
            st['0/0'] = False  # default value
            for x in db.TopologySourceIPFilter.objects.filter(topology=topo):
                sn = str('%s/%d' % (x.ip, x.mask))
                st[sn] = sn

            # check that the new filter isn't covered by one of the existing ones
            new_sn = '%s/%d' % (ip, mask)
            sn_within = st[ip]
            if sn_within:
                messages.error(
                    request,
                    'The range %s is already covered by the existing filter %s.'
                    % (new_sn, sn_within))
                return HttpResponseRedirect('/topology%d/' % tid)
            else:
                new_sip = db.TopologySourceIPFilter()
                new_sip.topology = topo
                new_sip.ip = ip
                new_sip.mask = mask
                new_sip.save()
                messages.success(
                    request,
                    "%s (%s) has been added to the permitted source IP range list."
                    % (new_sip.subnet_mask_str(), new_sn))
                return HttpResponseRedirect('/topology%d/' % tid)
    else:
        form = APSIPForm()
    return direct_to_template(request, tn, {'form': form, 'tid': tid})
コード例 #4
0
ファイル: TopologyResolver.py プロジェクト: dound/vns
 def __init__(self):
     SubnetTree.__init__(self)
     self.keys = {}
コード例 #5
0
ファイル: TopologyResolver.py プロジェクト: dound/vns
 def __delitem__(self, key):
     SubnetTree.__delitem__(self, key)
     self.keys.__delitem__(key)
コード例 #6
0
ファイル: TopologyResolver.py プロジェクト: dound/vns
 def __setitem__(self, key, value):
     SubnetTree.__setitem__(self, key, value)
     self.keys.__setitem__(key, value)
コード例 #7
0
ファイル: protocol.py プロジェクト: xiaopeng163/yabgp
class BGP(protocol.Protocol):
    """Protocol class for BGP 4"""
    def __init__(self):
        """Create a BGP protocol.
        """
        self.fsm = None
        self.peer_id = None

        self.disconnected = False
        self._receive_buffer = b''
        self.fourbytesas = False
        self.add_path_ipv4_receive = False
        self.add_path_ipv4_send = False
        self.adj_rib_in = {k: {} for k in CONF.bgp.afi_safi}
        self.adj_rib_out = {k: {} for k in CONF.bgp.afi_safi}
        self.adj_rib_in_ipv4_tree = SubnetTree()

        # statistic
        self.msg_sent_stat = {
            'Opens': 0,
            'Notifications': 0,
            'Updates': 0,
            'Keepalives': 0,
            'RouteRefresh': 0
        }
        self.msg_recv_stat = {
            'Opens': 0,
            'Notifications': 0,
            'Updates': 0,
            'Keepalives': 0,
            'RouteRefresh': 0
        }
        self.send_version = {
            'ipv4': 0,
            'flowspec': 0,
            'sr_policy': 0,
            'mpls_vpn': 0
        }
        self.receive_version = {
            'ipv4': 0,
            'flowspec': 0,
            'sr_policy': 0,
            'mpls_vpn': 0
        }

        self.flowspec_send_dict = {}
        self.flowspec_receive_dict = {}
        self.sr_send_dict = {}
        self.sr_receive_dict = {}
        self.mpls_vpn_send_dict = {}
        self.mpls_vpn_receive_dict = {}

    @property
    def handler(self):
        # this is due to self.factory is assigned at runtime
        return self.factory.handler

    def init_rib(self):
        self.adj_rib_in = {k: {} for k in CONF.bgp.afi_safi}
        self.adj_rib_out = {k: {} for k in CONF.bgp.afi_safi}

    def connectionMade(self):
        """
        Starts the initial negotiation of the protocol
        """
        self.init_rib()
        # Set transport socket options
        self.transport.setTcpNoDelay(True)
        # set tcp option if you want
        #  self.transport.getHandle().setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, md5sig)

        LOG.info("[%s]TCP Connection established", self.factory.peer_addr)

        # Set the local BGP id from the local IP address if it's not set
        if self.factory.bgp_id is None:
            try:
                local_host_addr = netaddr.IPAddress(
                    self.transport.getHost().host)
                if 'IPv6' in local_host_addr.info.__iter__():
                    self.factory.bgp_id = int(netaddr.IPAddress('127.0.0.1'))
                else:
                    self.factory.bgp_id = int(local_host_addr)
            except Exception as e:
                LOG.error(e)
                error_str = traceback.format_exc()
                LOG.debug(error_str)
                self.factory.bgp_id = int(netaddr.IPAddress('127.0.0.1'))
        try:
            self.fsm.connection_made()
        except Exception as e:
            LOG.error(e)
            error_str = traceback.format_exc()
            LOG.debug(error_str)

    def connectionLost(self, reason):
        """Called when the associated connection was lost.
        :param reason: the reason of lost connection.
        """
        LOG.debug('Called connectionLost')
        self.init_rib()
        self.handler.on_connection_lost(self)

        # Don't do anything if we closed the connection explicitly ourselves
        if self.disconnected:
            self.factory.connection_closed(self)
            LOG.info('Connection lost return and do nothing')
            return

        LOG.info("[%s]Connection lost:%s", self.factory.peer_addr,
                 reason.getErrorMessage())

        try:
            # tell FSM that TCP connection is lost.
            self.fsm.connection_failed()
        except Exception as e:
            LOG.error(e)
            error_str = traceback.format_exc()
            LOG.debug(error_str)

    def dataReceived(self, data):
        """
        Appends newly received data to the receive buffer, and
        then attempts to parse as many BGP messages as possible.

        :param data: the data received from TCP buffer.
        """

        # Buffer possibly incomplete data first
        self._receive_buffer += data
        while self.parse_buffer():
            pass

    def parse_buffer(self):
        """
        Parse TCP buffer data.

        :return: True or False
        """
        buf = self._receive_buffer

        if len(buf) < bgp_cons.HDR_LEN:
            # Every BGP message is at least 19 octets. Maybe the rest
            # hasn't arrived yet.
            return False

        # Check whether the first 16 octets of the buffer consist of
        # the BGP marker (all bits one)
        if buf[:16] != 16 * b'\xff':
            self.fsm.header_error(bgp_cons.ERR_MSG_HDR_CONN_NOT_SYNC)
            return False
            # Parse the BGP header
        try:
            marker, length, msg_type = struct.unpack('!16sHB',
                                                     buf[:bgp_cons.HDR_LEN])
        except Exception as e:
            LOG.error(e)
            error_str = traceback.format_exc()
            LOG.debug(error_str)
            self.fsm.header_error(bgp_cons.ERR_MSG_HDR_CONN_NOT_SYNC)
            return False
            # Check the length of the message, must be less than 4096, bigger than 19
        if length < bgp_cons.HDR_LEN or length > bgp_cons.MAX_LEN:
            self.fsm.header_error(bgp_cons.ERR_MSG_HDR_BAD_MSG_LEN,
                                  struct.pack('!H', length))
            # Check whether the entire message is already available
        if len(buf) < length:
            return False
        msg = buf[bgp_cons.HDR_LEN:length]
        t = time.time()  # the time when received that packet.
        try:
            if msg_type == bgp_cons.MSG_OPEN:
                try:
                    self._open_received(timestamp=t, msg=msg)
                except excep.MessageHeaderError as e:
                    LOG.error(e)
                    self.fsm.header_error(suberror=e.sub_error)
                    return False
                except excep.OpenMessageError as e:
                    LOG.error(e)
                    self.fsm.open_message_error(suberror=e.sub_error)
                    return False

            elif msg_type == bgp_cons.MSG_UPDATE:
                self._update_received(timestamp=t, msg=msg)

            elif msg_type == bgp_cons.MSG_NOTIFICATION:
                self._notification_received(Notification().parse(msg))

            elif msg_type == bgp_cons.MSG_KEEPALIVE:
                try:
                    self._keepalive_received(timestamp=t, msg=msg)
                except excep.MessageHeaderError as e:
                    LOG.error(e)
                    self.fsm.header_error(suberror=e.sub_error)
                    return False
            elif msg_type in (bgp_cons.MSG_ROUTEREFRESH,
                              bgp_cons.MSG_CISCOROUTEREFRESH):
                route_refresh_msg = RouteRefresh().parse(msg)
                self._route_refresh_received(msg=route_refresh_msg,
                                             msg_type=msg_type)
            else:
                # unknown message type
                self.fsm.header_error(bgp_cons.ERR_MSG_HDR_BAD_MSG_TYPE,
                                      struct.pack('!H', msg_type))
        except Exception as e:
            LOG.error(e)
            error_str = traceback.format_exc()
            LOG.debug(error_str)
        self._receive_buffer = self._receive_buffer[length:]
        return True

    def closeConnection(self):
        """Close the connection"""

        if self.transport.connected:
            self.transport.loseConnection()
            self.disconnected = True

    def _update_received(self, timestamp, msg):
        """Called when a BGP Update message was received."""
        result = Update().parse(timestamp, msg, self.fourbytesas,
                                self.add_path_ipv4_receive,
                                self.add_path_ipv4_send)
        if result['sub_error']:
            msg = {
                'attr': result['attr'],
                'nlri': result['nlri'],
                'withdraw': result['withdraw'],
                'hex': repr(result['hex'])
            }

            self.handler.on_update_error(self, timestamp, msg)

            LOG.error('[%s] Update message error: sub error=%s',
                      self.factory.peer_addr, result['sub_error'])
            self.msg_recv_stat['Updates'] += 1
            self.fsm.update_received()
            return

        afi_safi = None
        # process messages
        if result['nlri'] or result['withdraw']:
            afi_safi = 'ipv4'
        elif result['attr'].get(14):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']]
        elif result['attr'].get(15):
            afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']]

        msg = {
            'attr': result['attr'],
            'nlri': result['nlri'],
            'withdraw': result['withdraw'],
            'afi_safi': afi_safi
        }

        self.update_receive_verion(result['attr'], result['nlri'],
                                   result['withdraw'])

        if CONF.bgp.rib:
            # try to update bgp rib in
            if msg.get('afi_safi') == 'ipv4':
                self.update_rib_in_ipv4(msg)
                LOG.info(msg)
        self.handler.update_received(self, timestamp, msg)

        self.msg_recv_stat['Updates'] += 1
        self.fsm.update_received()

    def send_update(self, msg):
        """
        send update message to the peer
        :param msg: message dictionary
        :return:
        """
        try:
            msg_update = Update().construct(msg, self.fourbytesas,
                                            self.add_path_ipv4_send)
            reactor.callFromThread(self.write_tcp_thread, msg_update)
            self.msg_sent_stat['Updates'] += 1

            return True
        except Exception as e:
            LOG.error(e)
            return False

    def write_tcp_thread(self, msg):
        self.transport.write(msg)

    def send_notification(self, error, sub_error, data=b''):
        """
        send BGP notification message

        :param error:
        :param sub_error:
        :param data:
        :return:
        """
        self.msg_sent_stat['Notifications'] += 1
        LOG.info(
            "[%s]Send a BGP Notification message to the peer "
            "[Error: %s, Suberror: %s, Error data: %s ]",
            self.factory.peer_addr, error, sub_error, repr(data))
        # message statistic
        self.msg_sent_stat['Notifications'] += 1
        # construct message
        msg_notification = Notification().construct(error, sub_error, data)
        # send message
        self.transport.write(msg_notification)

    def _notification_received(self, msg):
        """
        BGP notification message received.
        """
        self.msg_recv_stat['Notifications'] += 1
        error_str = bgp_cons.NOTIFICATION_ERROR_CODES_DICT.get(msg[0])
        if error_str:
            sub_error_str = bgp_cons.NOTIFICATION_SUB_ERROR_CODES_DICT.get(
                msg[0]).get(msg[1])
        else:
            sub_error_str = None
        LOG.info(
            '[%s]Notification message received, error: %s, sub error: %s, data=%s',
            self.factory.peer_addr, error_str, sub_error_str, msg[2])

        nofi_msg = {
            'error': error_str,
            'sub_error': sub_error_str,
            'data': repr(msg[2])
        }

        self.handler.notification_received(self, nofi_msg)

        self.fsm.notification_received(msg[0], msg[1])

        LOG.debug('offline')

    def send_keepalive(self):
        """
        send BGP keepalive message.
        """
        self.msg_sent_stat['Keepalives'] += 1
        LOG.info("[%s]Send a BGP KeepAlive message to the peer.",
                 self.factory.peer_addr)
        # message statistci
        # self.msg_sent_stat['Keepalives'] += 1
        # construct message
        msg_keepalive = KeepAlive().construct()
        # send message
        self.transport.write(msg_keepalive)

    def _keepalive_received(self, timestamp, msg):
        """
            process keepalive message

            :param timestamp:
            :param msg:
            :return:
        """

        # deal with all request in internal message queue
        # until the queue is empty
        while not self.handler.inter_mq.empty(
        ) and self.msg_recv_stat['Keepalives'] > 0:
            inter_msg = self.handler.inter_mq.get()
            LOG.debug('Get %s message %s from internal queue',
                      inter_msg['type'], inter_msg['msg'])
            if inter_msg['type'] == 'notification':
                self.send_notification(inter_msg['msg']['error'],
                                       inter_msg['msg']['sub_error'],
                                       inter_msg['msg']['data'])
            elif inter_msg['type'] == 'update':
                self.send_update(inter_msg['msg'])

        self.msg_recv_stat['Keepalives'] += 1

        self.handler.keepalive_received(self, timestamp)

        LOG.info("[%s]A BGP KeepAlive message was received from peer.",
                 self.factory.peer_addr)
        KeepAlive().parse(msg)

        self.fsm.keep_alive_received()

    def capability_negotiate(self):
        """
        Open message capability negotiation
        :return:
        """
        # if received open message from remote peer firstly
        # then copy peer's capability to local according to the
        # local support. best effort support.
        if cfg.CONF.bgp.running_config['capability']['remote']:
            unsupport_cap = []
            for capability in cfg.CONF.bgp.running_config['capability'][
                    'local']:
                if capability not in cfg.CONF.bgp.running_config['capability'][
                        'remote']:
                    unsupport_cap.append(capability)
            for capability in unsupport_cap:
                cfg.CONF.bgp.running_config['capability']['local'].pop(
                    capability)

    def send_open(self):
        """
        send open message

        :return:
        """
        # construct Open message
        self.capability_negotiate()
        open_msg = Open(
            version=bgp_cons.VERSION, asn=self.factory.my_asn, hold_time=self.fsm.hold_time,
            bgp_id=self.factory.bgp_id). \
            construct(cfg.CONF.bgp.running_config['capability']['local'])
        if 'add_path' in cfg.CONF.bgp.running_config['capability']['local']:
            # check add path feature, send add path condition:
            # local support send or both
            # remote support receive or both
            if cfg.CONF.bgp.running_config['capability']['local']['add_path'] in \
                    ['ipv4_send', 'ipv4_both']:
                if cfg.CONF.bgp.running_config['capability']['remote'].get('add_path') in \
                        ['ipv4_receive', 'ipv4_both']:
                    self.add_path_ipv4_send = True
        # send message
        self.transport.write(open_msg)
        self.msg_sent_stat['Opens'] += 1
        LOG.info("[%s]Send a BGP Open message to the peer.",
                 self.factory.peer_addr)
        LOG.info("[%s]Probe's Capabilities:", self.factory.peer_addr)
        for key in cfg.CONF.bgp.running_config['capability']['local']:
            LOG.info("--%s = %s", key,
                     cfg.CONF.bgp.running_config['capability']['local'][key])

    def _open_received(self, timestamp, msg):
        """
        porcess open message

        :param timestamp: timestamp that received this message
        :param msg: binary raw message data
        :return:
        """

        self.msg_recv_stat['Opens'] += 1
        open_msg = Open()
        parse_result = open_msg.parse(msg)
        if self.fsm.bgp_peering.peer_asn != open_msg.asn:
            raise excep.OpenMessageError(
                sub_error=bgp_cons.ERR_MSG_OPEN_BAD_PEER_AS)

        # Open message Capabilities negotiation
        cfg.CONF.bgp.running_config['capability'][
            'remote'] = open_msg.capa_dict
        LOG.info("[%s]A BGP Open message was received", self.factory.peer_addr)
        LOG.info('--version = %s', open_msg.version)
        LOG.info('--ASN = %s', open_msg.asn)
        LOG.info('--hold time = %s', open_msg.hold_time)
        LOG.info('--id = %s', open_msg.bgp_id)
        LOG.info("[%s]Neighbor's Capabilities:", self.factory.peer_addr)
        for key in cfg.CONF.bgp.running_config['capability']['remote']:
            if key == 'four_bytes_as':
                self.fourbytesas = True
            elif key == 'add_path':
                if cfg.CONF.bgp.running_config['capability']['remote']['add_path'] in \
                        ['ipv4_send', 'ipv4_both']:
                    if cfg.CONF.bgp.running_config['capability']['local']['add_path'] in \
                            ['ipv4_receive', 'ipv4_both']:
                        self.add_path_ipv4_receive = True

            LOG.info("--%s = %s", key,
                     cfg.CONF.bgp.running_config['capability']['remote'][key])

        self.peer_id = open_msg.bgp_id
        self.bgp_peering.set_peer_id(open_msg.bgp_id)

        self.negotiate_hold_time(open_msg.hold_time)
        self.fsm.open_received()

        self.handler.open_received(self, timestamp, parse_result)

    def send_route_refresh(self, afi, safi, res=0):
        """
        Send bgp route refresh message
        :param afi: address family
        :param safi: sub address family
        :param res: reserve, default is 0
        """
        # check if the peer support route refresh
        if 'cisco_route_refresh' in cfg.CONF.bgp.running_config['capability'][
                'remote']:
            type_code = bgp_cons.MSG_CISCOROUTEREFRESH
        elif 'route_refresh' in cfg.CONF.bgp.running_config['capability'][
                'remote']:
            type_code = bgp_cons.MSG_ROUTEREFRESH
        else:
            return False
        # check if the peer support this address family
        if (afi, safi) not in cfg.CONF.bgp.running_config['capability'][
                'remote']['afi_safi']:
            return False
        # construct message
        msg_routerefresh = RouteRefresh(afi, safi, res).construct(type_code)
        # send message
        self.transport.write(msg_routerefresh)
        self.msg_sent_stat['RouteRefresh'] += 1
        LOG.info("[%s]Send BGP RouteRefresh message to the peer.",
                 self.factory.peer_addr)
        return True

    def _route_refresh_received(self, msg, msg_type):
        """
        Route Refresh message received.

        :param msg: msg content
        :param msg_type: message type 5 or 128
        """
        self.msg_recv_stat['RouteRefresh'] += 1
        LOG.info('[%s]Route Refresh message received, afi=%s, res=%s, safi=%s',
                 self.factory.peer_addr, msg[0], msg[1], msg[2])
        nofi_msg = {'afi': msg[0], 'res': msg[1], 'safi': msg[2]}

        self.handler.route_refresh_received(self, nofi_msg, msg_type)

    def negotiate_hold_time(self, hold_time):
        """Negotiates the hold time"""

        self.fsm.hold_time = min(self.fsm.hold_time, hold_time)
        if self.fsm.hold_time != 0 and self.fsm.hold_time < 3:
            self.fsm.open_message_error(
                bgp_cons.ERR_MSG_OPEN_UNACCPT_HOLD_TIME)
            # Derived times
        self.fsm.keep_alive_time = self.fsm.hold_time / 3
        LOG.info("[%s]Hold time:%s,Keepalive time:%s", self.factory.peer_addr,
                 self.fsm.hold_time, self.fsm.keep_alive_time)

    def update_rib_out_ipv4(self, msg):
        try:
            for prefix in msg['withdraw']:
                if prefix in self.adj_rib_out['ipv4']:
                    self.send_version['ipv4'] += 1
                    self.adj_rib_out['ipv4'].pop(prefix)
            for prefix in msg['nlri']:
                if prefix not in self.adj_rib_out['ipv4'].keys():
                    self.send_version['ipv4'] += 1
                else:
                    if msg['attr'] == self.adj_rib_out['ipv4'][prefix]:
                        pass
                    else:
                        self.send_version['ipv4'] += 1
                self.adj_rib_out['ipv4'][prefix] = msg['attr']
            return True
        except Exception as e:
            LOG.error(e)
            return False

    def update_rib_in_ipv4(self, msg):
        try:
            for prefix in msg['withdraw']:
                if prefix in self.adj_rib_in['ipv4']:
                    self.receive_version['ipv4'] += 1
                    self.adj_rib_in['ipv4'].pop(prefix)
                    try:
                        self.adj_rib_in_ipv4_tree.remove(prefix)
                    except RuntimeError as e:
                        if e.__str__() == 'patricia_lookup failed.':
                            pass
                        else:
                            return False
            for prefix in msg['nlri']:
                if prefix not in self.adj_rib_in['ipv4'].keys():
                    self.receive_version['ipv4'] += 1
                else:
                    if msg['attr'] == self.adj_rib_in['ipv4'][prefix]:
                        pass
                    else:
                        self.receive_version['ipv4'] += 1
                self.adj_rib_in['ipv4'][prefix] = msg['attr']
                try:
                    self.adj_rib_in_ipv4_tree.remove(prefix)
                    LOG.info("remove a repeate key in tree. %s" % prefix)
                except RuntimeError as e:
                    if e.__str__() == 'patricia_lookup failed.':
                        pass
                    else:
                        return False
                self.adj_rib_in_ipv4_tree[prefix] = prefix
            return True
        except Exception as e:
            LOG.error(e)
            LOG.debug(traceback.format_exc())
            return False

    def ip_longest_match(self, prefix_ip):
        results = {}
        if '/' in prefix_ip:
            return {
                'prefix': prefix_ip,
                'attr': self.adj_rib_in['ipv4'].get(prefix_ip)
            }
        if prefix_ip in self.adj_rib_in_ipv4_tree:
            prefix = self.adj_rib_in_ipv4_tree[prefix_ip]
            return {
                'prefix': prefix,
                'attr': self.adj_rib_in['ipv4'].get(prefix)
            }
        return results

    def update_send_verion(self, peer_ip, attr, nlri, withdraw):
        # ipv4 send
        # if (attr and nlri) or withdraw:
        #     if withdraw:
        #         for prefix in withdraw:
        #             if prefix in self.ipv4_send_dict:
        #                 self.send_version['ipv4'] += 1
        #                 del self.ipv4_send_dict[prefix]
        #             else:
        #                 LOG.info("Do not have %s in send ipv4 dict" % prefix)
        #     if attr and nlri:
        #         for prefix in nlri:
        #             if prefix not in self.ipv4_send_dict:
        #                 self.send_version['ipv4'] += 1
        #                 self.ipv4_send_dict[prefix] = attr
        #             else:
        #                 if attr == self.ipv4_send_dict[prefix]:
        #                     pass
        #                 else:
        #                     self.send_version['ipv4'] += 1
        #                     self.ipv4_send_dict[prefix] = attr
        # flowspec sr mpls send
        if 14 in attr:
            if attr[14]['afi_safi'] == [1, 133]:
                LOG.info("send flowspec")
                for prefix in attr[14]['nlri']:
                    value = copy.deepcopy(attr)
                    value14 = value[14]
                    del value14['nlri']
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) not in self.flowspec_send_dict:
                        self.send_version['flowspec'] += 1
                        self.flowspec_send_dict[str(key)] = value
                    else:
                        if value == self.flowspec_send_dict[str(key)]:
                            pass
                        else:
                            self.send_version['flowspec'] += 1
                            self.flowspec_send_dict[str(key)] = value
            elif attr[14]['afi_safi'] == [1, 73]:
                LOG.info('send sr')
                key = "{"
                for k in sorted(attr[14]['nlri'].keys()):
                    key += '"' + k + '"'
                    key += ':'
                    key += '"' + str(attr[14]['nlri'][k]) + '"'
                    key += ','
                key = key[:-1]
                key += "}"
                if str(key) not in self.sr_send_dict:
                    self.send_version['sr_policy'] += 1
                    self.sr_send_dict[str(key)] = attr
                else:
                    if attr == self.sr_send_dict[str(key)]:
                        pass
                    else:
                        self.send_version['sr_policy'] += 1
                        self.sr_send_dict[str(key)] = attr
            elif attr[14]['afi_safi'] == [1, 128]:
                LOG.info("send mpls_vpn")
                for prefix in attr[14]['nlri']:
                    value = copy.deepcopy(attr)
                    value14 = value[14]
                    del value14['nlri']
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) not in self.mpls_vpn_send_dict:
                        self.send_version['mpls_vpn'] += 1
                        self.mpls_vpn_send_dict[str(key)] = value
                    else:
                        if value == self.mpls_vpn_send_dict[str(key)]:
                            pass
                        else:
                            self.send_version['mpls_vpn'] += 1
                            self.mpls_vpn_send_dict[str(key)] = value
        # flowspec sr mpls_vpn withdraw
        if 15 in attr:
            if attr[15]['afi_safi'] == [1, 133]:
                LOG.info("withdraw flowspec")
                for prefix in attr[15]['withdraw']:
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) in self.flowspec_send_dict:
                        self.send_version['flowspec'] += 1
                        del self.flowspec_send_dict[str(key)]
                    else:
                        LOG.info("Do not have %s in send flowspec dict" % key)
            elif attr[15]['afi_safi'] == [1, 73]:
                LOG.info('withdraw sr')
                key = "{"
                for k in sorted(attr[15]['nlri'].keys()):
                    key += '"' + k + '"'
                    key += ':'
                    key += '"' + str(attr[15]['nlri'][k]) + '"'
                    key += ','
                key = key[:-1]
                key += "}"
                if str(key) in self.sr_send_dict:
                    self.send_version['sr_policy'] += 1
                    del self.sr_send_dict[str(key)]
                else:
                    LOG.info("Do not have %s in send flowspec dict" % key)
            elif attr[15]['afi_safi'] == [1, 128]:
                LOG.info("withdraw mpls_vpn")
                for prefix in attr[15]['withdraw']:
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) in self.mpls_vpn_send_dict:
                        self.send_version['mpls_vpn'] += 1
                        del self.mpls_vpn_send_dict[str(key)]
                    else:
                        LOG.info("Do not have %s in send flowspec dict" % key)

    def update_receive_verion(self, attr, nlri, withdraw):
        # receive ipv4
        # if (attr and nlri) or withdraw:
        #     if withdraw:
        #         for prefix in withdraw:
        #             if prefix in self.ipv4_receive_dict:
        #                 self.receive_version['ipv4'] += 1
        #                 del self.ipv4_receive_dict[prefix]
        #             else:
        #                 LOG.info("Do not have %s in recieve ipv4 dict" % prefix)
        #     if attr and nlri:
        #         for prefix in nlri:
        #             if prefix not in self.ipv4_receive_dict:
        #                 self.receive_version['ipv4'] += 1
        #                 self.ipv4_receive_dict[prefix] = attr
        #             else:
        #                 if attr == self.ipv4_receive_dict[prefix]:
        #                     pass
        #                 else:
        #                     self.receive_version['ipv4'] += 1
        #                     self.ipv4_receive_dict[prefix] = attr
        # receive flowspec sr mpls_vpn send
        if 14 in attr:
            if attr[14]['afi_safi'] == [1, 133]:
                LOG.info("recieve flowspec send")
                for prefix in attr[14]['nlri']:
                    value = copy.deepcopy(attr)
                    value14 = value[14]
                    del value14['nlri']
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) not in self.flowspec_receive_dict:
                        self.receive_version['flowspec'] += 1
                        self.flowspec_receive_dict[str(key)] = value
                    else:
                        if value == self.flowspec_receive_dict[str(key)]:
                            pass
                        else:
                            self.receive_version['flowspec'] += 1
                            self.flowspec_receive_dict[str(key)] = value
            elif attr[14]['afi_safi'] == [1, 73]:
                LOG.info('recieve sr send')
            elif attr[14]['afi_safi'] == [1, 128]:
                LOG.info("receive send mpls_vpn")
                for prefix in attr[14]['nlri']:
                    value = copy.deepcopy(attr)
                    value14 = value[14]
                    del value14['nlri']
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) not in self.mpls_vpn_receive_dict:
                        self.receive_version['mpls_vpn'] += 1
                        self.mpls_vpn_receive_dict[str(key)] = value
                    else:
                        if value == self.mpls_vpn_receive_dict[str(key)]:
                            pass
                        else:
                            self.receive_version['mpls_vpn'] += 1
                            self.mpls_vpn_receive_dict[str(key)] = value
        # receive flowspec sr mpls withdraw
        if 15 in attr:
            if attr[15]['afi_safi'] == [1, 133]:
                LOG.info("recieve flowspec withdraw")
                for prefix in attr[15]['withdraw']:
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) in self.flowspec_receive_dict:
                        self.receive_version['flowspec'] += 1
                        del self.flowspec_receive_dict[str(key)]
                    else:
                        LOG.info("Do not have %s in receive flowspec dict" %
                                 prefix)
            elif attr[15]['afi_safi'] == [1, 73]:
                LOG.info('recieve sr withdraw')
            elif attr[15]['afi_safi'] == [1, 128]:
                LOG.info("recieve withdraw mpls_vpn")
                for prefix in attr[15]['withdraw']:
                    key = "{"
                    for k in sorted(prefix.keys()):
                        key += '"' + k + '"'
                        key += ':'
                        key += '"' + str(prefix[k]) + '"'
                        key += ','
                    key = key[:-1]
                    key += "}"
                    if str(key) in self.mpls_vpn_receive_dict:
                        self.receive_version['mpls_vpn'] += 1
                        del self.mpls_vpn_receive_dict[str(key)]
                    else:
                        LOG.info("Do not have %s in receive mpls_vpn dict" %
                                 key)
コード例 #8
0
ファイル: lpm.py プロジェクト: vmorokhx/sonic-mgmt
class LpmDict():
    class IpInterval:
        def __init__(self, s):
            self._start = s
            self._end = s

        def __init__(self, s, e):
            assert s <= e
            self._start = s
            self._end = e

        # __len__ has hard limit on returning long int
        def length(self):
            return int(self._end) - int(self._start)

        def contains(self, ip):
            return ip >= self._start and ip <= self._end

        def get_first_ip(self):
            return str(self._start)

        def get_last_ip(self):
            return str(self._end)

        def get_random_ip(self):
            diff = self.length()
            return str(self._start + random.randint(0, diff))

        def __str__(self):
            return str(self._start) + ' - ' + str(self._end)

    def __init__(self, ipv4=True):
        self._ipv4 = ipv4
        self._prefix_set = set()
        self._subnet_tree = SubnetTree()
        # 0.0.0.0 is a non-routable meta-address that needs to be skipped
        self._boundaries = {
            ip_address(u'0.0.0.0'): 1
        } if ipv4 else {
            ip_address(u'::'): 1
        }

    def __setitem__(self, key, value):
        prefix = ip_network(six.text_type(key))
        # add the current key to self._prefix_set only when it is not the default route and it is not a duplicate key
        if prefix.prefixlen and key not in self._prefix_set:
            boundary = prefix[0]
            self._boundaries[boundary] = self._boundaries.get(boundary, 0) + 1
            if prefix[-1] != ip_address(
                    u'255.255.255.255') and prefix[-1] != ip_address(
                        u'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'):
                next_boundary = prefix[-1] + 1
                self._boundaries[next_boundary] = self._boundaries.get(
                    next_boundary, 0) + 1
            self._prefix_set.add(key)
        self._subnet_tree.__setitem__(key, value)

    def __getitem__(self, key):
        return self._subnet_tree[key]

    def __delitem__(self, key):
        if '/0' not in key:
            prefix = ip_network(six.text_type(key))
            boundary = prefix[0]
            next_boundary = prefix[-1] + 1
            self._boundaries[boundary] = self._boundaries.get(boundary) - 1
            if not self._boundaries[boundary]:
                del self._boundaries[boundary]
            self._boundaries[next_boundary] = self._boundaries.get(
                next_boundary) - 1
            if not self._boundaries[next_boundary]:
                del self._boundaries[next_boundary]
            self._prefix_set.remove(key)
        self._subnet_tree.__delitem__(key)

    def ranges(self):
        sorted_boundaries = sorted(self._boundaries.keys())
        ranges = []
        for index, boundary in enumerate(sorted_boundaries):
            if index != len(sorted_boundaries) - 1:
                interval = self.IpInterval(sorted_boundaries[index],
                                           sorted_boundaries[index + 1] - 1)
            else:
                if self._ipv4:
                    interval = self.IpInterval(sorted_boundaries[index],
                                               ip_address(u'255.255.255.255'))
                else:
                    interval = self.IpInterval(
                        sorted_boundaries[index],
                        ip_address(u'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'))
            ranges.append(interval)
        return ranges

    def contains(self, key):
        return key in self._subnet_tree
コード例 #9
0
ファイル: TopologyResolver.py プロジェクト: yhyan/vns
 def __delitem__(self, key):
     SubnetTree.__delitem__(self, key)
     self.keys.__delitem__(key)
コード例 #10
0
ファイル: TopologyResolver.py プロジェクト: yhyan/vns
 def __setitem__(self, key, value):
     SubnetTree.__setitem__(self, key, value)
     self.keys.__setitem__(key, value)
コード例 #11
0
ファイル: TopologyResolver.py プロジェクト: yhyan/vns
 def __init__(self):
     SubnetTree.__init__(self)
     self.keys = {}