Ejemplo n.º 1
0
	def __init__ (self,what,afi,safi,data=''):
		self.afi = AFI(afi)
		self.safi = SAFI(afi)
		Operational.__init__(
			self,what,
			'%s%s%s' % (self.afi.pack(),self.safi.pack(),data)
		)
Ejemplo n.º 2
0
Archivo: nlri.py Proyecto: cys3c/exabgp
	def unpack_nlri (cls, afi, safi, data, action, addpath):
		if not cls.logger:
			cls.logger = Logger()
		cls.logger.parser(LazyNLRI(afi,safi,data))

		key = '%s/%s' % (AFI(afi),SAFI(safi))
		if key in cls.registered_nlri:
			return cls.registered_nlri[key].unpack_nlri(afi,safi,data,action,addpath)
		raise Notify(3,0,'trying to decode unknown family %s/%s' % (AFI(afi),SAFI(safi)))
Ejemplo n.º 3
0
class Inet(Address):
    _UNICAST = SAFI(SAFI.unicast)
    _MULTICAST = SAFI(SAFI.multicast)

    _multicast_range = set(range(224, 240))  # 239 is last
    """An IP in the 4 bytes format"""
    # README: yep, we should surely change this _ name here
    _af = {
        AFI.ipv4: socket.AF_INET,
        AFI.ipv6: socket.AF_INET6,
    }

    _afi = {
        socket.AF_INET: AFI.ipv4,
        socket.AF_INET6: AFI.ipv6,
    }

    length = {
        AFI.ipv4: 4,
        AFI.ipv6: 16,
    }

    def __init__(self, afi, safi, packed):
        if safi:  # XXX: FIXME: we use a constant which is zero - reference it explicitly
            Address.__init__(self, afi, safi)
        elif ord(packed[0]) in self._multicast_range:
            Address.__init__(self, afi, self._MULTICAST)
        else:
            Address.__init__(self, afi, self._UNICAST)

        self.packed = packed
        self.ip = socket.inet_ntop(self._af[self.afi], self.packed)

    def pack(self):
        return self.packed

    def __len__(self):
        return len(self.packed)

    def inet(self):
        return self.ip

    def __str__(self):
        return self.inet()

    def __cmp__(self, other):
        if self.packed == other.packed:
            return 0
        if self.packed < other.packed:
            return -1
        return 1

    def __repr__(self):
        return "<%s value %s>" % (str(
            self.__class__).split("'")[1].split('.')[-1], str(self))
Ejemplo n.º 4
0
    def _nlri(afi, safi, bgp, action, addpath):
        labels = []
        rd = ''

        if addpath:
            path_identifier = bgp[:4]
            bgp = bgp[4:]
        else:
            path_identifier = None

        mask = ord(bgp[0])
        bgp = bgp[1:]

        if SAFI(safi).has_label():
            while bgp and mask >= 8:
                label = int(unpack('!L', chr(0) + bgp[:3])[0])
                bgp = bgp[3:]
                mask -= 24  # 3 bytes
                # The last 4 bits are the bottom of Stack
                # The last bit is set for the last label
                labels.append(label >> 4)
                # This is a route withdrawal
                if label == 0x800000 and action == IN.WITHDRAWN:
                    break
                # This is a next-hop
                if label == 0x000000:
                    break
                if label & 1:
                    break

        if SAFI(safi).has_rd():
            mask -= 8 * 8  # the 8 bytes of the route distinguisher
            rd = bgp[:8]
            bgp = bgp[8:]

        if mask < 0:
            raise Notify(3, 10, 'invalid length in NLRI prefix')

        if not bgp and mask:
            raise Notify(
                3, 10,
                'not enough data for the mask provided to decode the NLRI')

        size = CIDR.size(mask)

        if len(bgp) < size:
            raise Notify(
                3, 10, 'could not decode route with AFI %d sand SAFI %d' %
                (afi, safi))

        network, bgp = bgp[:size], bgp[size:]
        padding = '\0' * (IP.length(afi) - size)
        prefix = network + padding

        return labels, rd, path_identifier, mask, size, prefix, bgp
Ejemplo n.º 5
0
	def _add (self, tokeniser, afi_name, safi_names):
		self._check_duplicate(tokeniser,RaisedFamily)
		known = self.content.setdefault(AFI(AFI.value(afi_name)),[])

		for (idx_line,idx_column,line,safi_name) in safi_names:
			if safi_name not in AFI.implemented_safi(afi_name):
				raise RaisedFamily(Location(idx_line,idx_column,line),'the family pair afi/safi %s/%s is unimplemented' % (afi_name,safi_name))

			safi = SAFI(SAFI.value(safi_name))
			if safi in known:
				raise RaisedFamily(Location(idx_line,idx_column,line),'afi/safi pair already defined in this family')
			known.append(safi)
Ejemplo n.º 6
0
def _nlrifactory(afi, safi, bgp, action):
    labels = []
    rd = ''

    mask = ord(bgp[0])
    bgp = bgp[1:]

    if SAFI(safi).has_label():
        while bgp and mask >= 8:
            label = int(unpack('!L', chr(0) + bgp[:3])[0])
            bgp = bgp[3:]
            mask -= 24  # 3 bytes
            # The last 4 bits are the bottom of Stack
            # The last bit is set for the last label
            labels.append(label >> 4)
            # This is a route withdrawal
            if label == 0x800000 and action == IN.withdrawn:
                break
            # This is a next-hop
            if label == 0x000000:
                break
            if label & 1:
                break

    if SAFI(safi).has_rd():
        mask -= 8 * 8  # the 8 bytes of the route distinguisher
        rd = bgp[:8]
        bgp = bgp[8:]

    if mask < 0:
        raise Notify(3, 10, 'invalid length in NLRI prefix')

    if not bgp and mask:
        raise Notify(
            3, 10, 'not enough data for the mask provided to decode the NLRI')

    size = mask_to_bytes.get(mask, None)
    if size is None:
        raise Notify(3, 10, 'invalid netmask found when decoding NLRI')

    if len(bgp) < size:
        raise Notify(
            3, 10,
            'could not decode route with AFI %d sand SAFI %d' % (afi, safi))

    network, bgp = bgp[:size], bgp[size:]
    padding = '\0' * (NLRI.length[afi] - size)
    prefix = network + padding

    return labels, rd, mask, size, prefix, bgp
Ejemplo n.º 7
0
class EVPN(object):
    registered_evpn = dict()
    # CODE : NEED to be defined in the subclasses
    NAME = 'unknown'
    SHORT_NAME = 'unknown'

    # lower case to match the class Address API
    afi = AFI(AFI.l2vpn)
    safi = SAFI(SAFI.evpn)

    def __init__(self, packed):
        self.packed = packed

    def _prefix(self):
        return "evpn:%s:" % (self._name.get(self.CODE, 'unknown').lower())

    def __str__(self):
        return "evpn:%s:%s" % (self._name.get(self.CODE, 'unknown').lower(),
                               '0x' + ''.join('%02x' % ord(_)
                                              for _ in self.packed))

    def __repr__(self):
        return str(self)

    def pack(self):
        return pack('!BB', self.CODE, len(self.packed)) + self.packed

    def __len__(self):
        return len(self.packed) + 2

    # For subtype 2 (MAC/IP advertisement route),
    # we will have to ignore a part of the route, so this method will be overridden

    def __cmp__(self, other):
        if not isinstance(other, EVPN):
            return -1
        if self.CODE != other.CODE:
            return -1
        if self.packed != other.packed:
            return -1
        return 0

    def __hash__(self):
        return hash("%s:%s:%s:%s" %
                    (self.afi, self.safi, self.CODE, self.packed))

    @classmethod
    def register_evpn(cls):
        cls.registered_evpn[cls.CODE] = cls

    @classmethod
    def unpack(cls, data):
        code = ord(data[0])
        length = ord(data[1])

        if code in cls.registered_evpn:
            return cls.registered_evpn[code].unpack(data[length + 1:])
        klass = cls(data[length + 1:])
        klass.CODE = code
        return klass
Ejemplo n.º 8
0
    def ipv6(self, tokeniser):
        self._check_conflict()
        safi = tokeniser()

        if safi == 'unicast':
            self.content.append((AFI(AFI.ipv6), SAFI(SAFI.unicast)))
        elif safi == 'mpls-vpn':
            self.content.append((AFI(AFI.ipv6), SAFI(SAFI.mpls_vpn)))
        elif safi in ('flow'):
            self.content.append((AFI(AFI.ipv6), SAFI(SAFI.flow_ip)))
        elif safi == 'flow-vpn':
            self.content.append((AFI(AFI.ipv6), SAFI(SAFI.flow_vpn)))
        else:
            raise Raised('unknow family safi %s' % safi)

        self._drop_colon(tokeniser)
Ejemplo n.º 9
0
 def register_nlri(klass):
     cls.registered_nlri['%d/%d' % (afi, safi)] = klass
     new = (AFI(afi), SAFI(safi))
     if new in cls.registered_nlri:
         raise RuntimeError('Tried to register %s/%s twice' % new)
     cls.registered_families.append(new)
     return klass
Ejemplo n.º 10
0
    def post(self):
        # self._family()
        self._split()
        # self.scope.to_context()
        routes = self.scope.pop(self.name)
        if routes:
            for route in routes:
                # if route.nlri.has_rd():
                if route.nlri.rd is not RouteDistinguisher.NORD:
                    route.nlri.safi = SAFI(SAFI.mpls_vpn)
                # elif route.nlri.has_label():
                elif route.nlri.labels is not Labels.NOLABEL:
                    route.nlri.safi = SAFI(SAFI.nlri_mpls)

            self.scope.extend('routes', routes)
        return True
Ejemplo n.º 11
0
    def rd(self, scope, name, command, tokens, safi):
        try:
            try:
                data = tokens.pop(0)
            except IndexError:
                return self.error.set(self.syntax)

            separator = data.find(':')
            if separator > 0:
                prefix = data[:separator]
                suffix = int(data[separator + 1:])

            if '.' in prefix:
                data = [chr(0), chr(1)]
                data.extend([chr(int(_)) for _ in prefix.split('.')])
                data.extend([chr(suffix >> 8), chr(suffix & 0xFF)])
                rd = ''.join(data)
            else:
                number = int(prefix)
                if number < pow(2, 16) and suffix < pow(2, 32):
                    rd = chr(0) + chr(0) + pack('!H', number) + pack(
                        '!L', suffix)
                elif number < pow(2, 32) and suffix < pow(2, 16):
                    rd = chr(0) + chr(2) + pack('!L', number) + pack(
                        '!H', suffix)
                else:
                    raise ValueError('invalid route-distinguisher %s' % data)

            nlri = scope[-1]['announce'][-1].nlri
            # overwrite nlri-mpls
            nlri.safi = SAFI(safi)
            nlri.rd = RouteDistinguisher(rd)
            return True
        except ValueError:
            return self.error.set(self.syntax)
Ejemplo n.º 12
0
    def unpack(cls, data, direction, negotiated):
        nlris = []

        # -- Reading AFI/SAFI
        afi, safi = unpack('!HB', data[:3])
        offset = 3
        data = data[offset:]

        if negotiated and (afi, safi) not in negotiated.families:
            raise Notify(
                3, 0, 'presented a non-negotiated family %s %s' %
                (AFI.create(afi), SAFI.create(safi)))

        # Do we need to handle Path Information with the route (AddPath)
        if direction == Direction.IN:
            addpath = negotiated.addpath.receive(afi, safi)
        else:
            addpath = negotiated.addpath.send(afi, safi)

        while data:
            nlri, data = NLRI.unpack_nlri(afi, safi, data, IN.WITHDRAWN,
                                          addpath)
            # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri
            if nlri:
                nlris.append(nlri)

        return cls(afi, safi, nlris)
Ejemplo n.º 13
0
class RouteRefresh(Message):
    TYPE = chr(Message.Type.ROUTE_REFRESH)

    request = 0
    start = 1
    end = 2

    def __init__(self, afi, safi, reserved=0):
        self.afi = AFI(afi)
        self.safi = SAFI(safi)
        self.reserved = Reserved(reserved)

    def messages(self, negotitated):
        return [
            self._message(
                '%s%s%s' %
                (self.afi.pack(), chr(self.reserved), self.safi.pack())),
        ]

    def __str__(self):
        return "REFRESH"

    def extensive(self):
        return 'route refresh %s/%d/%s' % (self.afi, self.reserved, self.safi)

    def families(self):
        return self._families[:]
Ejemplo n.º 14
0
class RouteRefresh (Message):
	ID = Message.ID.ROUTE_REFRESH
	TYPE = chr(Message.ID.ROUTE_REFRESH)

	request = 0
	start = 1
	end = 2

	def __init__ (self,afi,safi,reserved=0):
		self.afi = AFI(afi)
		self.safi = SAFI(safi)
		self.reserved = Reserved(reserved)

	def messages (self,negotitated):
		return [self._message('%s%s%s' % (self.afi.pack(),chr(self.reserved),self.safi.pack())),]

	def __str__ (self):
		return "REFRESH"

	def extensive (self):
		return 'route refresh %s/%d/%s' % (self.afi,self.reserved,self.safi)

	def families (self):
		return self._families[:]

	@classmethod
	def unpack_message (cls,data,negotitated):
		try:
			afi,reserved,safi = unpack('!HBB',data)
		except error:
			raise Notify(7,1,'invalid route-refresh message')
		if reserved not in (0,1,2):
			raise Notify(7,2,'invalid route-refresh message subtype')
		return RouteRefresh(afi,safi,reserved)
Ejemplo n.º 15
0
    def unpack_nlri(cls, afi, safi, bgp, action, addpath):
        nlri = cls(afi, safi, action)

        if addpath:
            nlri.path_info = PathInfo(bgp[:4])
            bgp = bgp[4:]

        mask = bgp[0]
        bgp = bgp[1:]

        _, rd_size = Family.size.get((afi, safi), (0, 0))
        rd_mask = rd_size * 8

        if safi.has_label():
            labels = []
            while mask - rd_mask >= 24:
                label = int(unpack('!L', bytes([0]) + bgp[:3])[0])
                bgp = bgp[3:]
                mask -= 24  # 3 bytes
                # The last 4 bits are the bottom of Stack
                # The last bit is set for the last label
                labels.append(label >> 4)
                # This is a route withdrawal
                if label == 0x800000 and action == IN.WITHDRAWN:
                    break
                # This is a next-hop
                if label == 0x000000:
                    break
                if label & 1:
                    break
            nlri.labels = Labels(labels)

        if rd_size:
            mask -= rd_mask  # the route distinguisher
            rd = bgp[:rd_size]
            bgp = bgp[rd_size:]
            nlri.rd = RouteDistinguisher(rd)

        if mask < 0:
            raise Notify(3, 10, 'invalid length in NLRI prefix')

        if not bgp and mask:
            raise Notify(
                3, 10,
                'not enough data for the mask provided to decode the NLRI')

        size = CIDR.size(mask)

        if len(bgp) < size:
            raise Notify(
                3, 10,
                'could not decode route with family %s (AFI %d) %s (SAFI %d)' %
                (AFI(afi), int(afi), SAFI(safi), int(safi)))

        network, bgp = bgp[:size], bgp[size:]

        nlri.cidr = CIDR(network + bytes(IP.length(afi) - size), mask)

        return nlri, bgp
Ejemplo n.º 16
0
    def unpack_nlri(cls, afi, safi, data, action, addpath):
        a, s = AFI.create(afi), SAFI.create(safi)
        log.debug(LazyNLRI(a, s, addpath, data), 'parser')

        key = '%s/%s' % (a, s)
        if key in cls.registered_nlri:
            return cls.registered_nlri[key].unpack_nlri(a, s, data, action, addpath)
        raise Notify(3, 0, 'trying to decode unknown family %s/%s' % (a, s))
Ejemplo n.º 17
0
 def unpack(capability, instance, data):
     # XXX: FIXME: should check that we have not yet seen the capability
     while data:
         afi = AFI.unpack(data[:2])
         safi = SAFI.unpack(data[2])
         sr = ord(data[3])
         instance.add_path(afi, safi, sr)
         data = data[4:]
     return instance
Ejemplo n.º 18
0
	def parse_api_refresh (self,command):
		tokens = formated(command).split(' ')[2:]
		if len(tokens) != 2:
			return False
		afi = AFI.value(tokens.pop(0))
		safi = SAFI.value(tokens.pop(0))
		if afi is None or safi is None:
			return False
		return RouteRefresh(afi,safi)
Ejemplo n.º 19
0
 def api_refresh(self, command):
     tokens = formated(command).split(' ')[2:]
     if len(tokens) != 2:
         return False
     afi = AFI.value(tokens.pop(0))
     safi = SAFI.value(tokens.pop(0))
     if afi is None or safi is None:
         return False
     return RouteRefresh(afi, safi)
Ejemplo n.º 20
0
	def unpack_capability (instance, data, capability=None):  # pylint: disable=W0613
		# XXX: FIXME: should check that we have not yet seen the capability
		while data:
			afi = AFI.unpack(data[:2])
			safi = SAFI.unpack(data[2])
			sr = ord(data[3])
			instance.add_path(afi,safi,sr)
			data = data[4:]
		return instance
Ejemplo n.º 21
0
	def unpack_capability (instance, data, capability=None):  # pylint: disable=W0613
		# XXX: FIXME: should check that we have not yet seen the capability
		while data:
			afi = AFI.unpack(data[:2])
			safi = SAFI.unpack(data[2])
			sr = ord_(data[3])
			instance.add_path(afi,safi,sr)
			data = data[4:]
		return instance
Ejemplo n.º 22
0
	def unpack (capability,instance,data):
		# XXX: FIXME: should check that we have not yet seen the capability
		while data:
			afi = AFI.unpack(data[:2])
			safi = SAFI.unpack(data[2])
			sr = ord(data[3])
			instance.add_path(afi,safi,sr)
			data = data[4:]
		return instance
Ejemplo n.º 23
0
	def unpack (cls,afi,safi,data,addpath,nexthop,action):
		if not cls.logger:
			cls.logger = Logger()
		cls.logger.parser(LazyFormat("parsing %s/%s nlri payload " % (afi,safi),data))

		key = '%d/%d' % (afi,safi)
		if key in cls.registered_nlri:
			return cls.registered_nlri[key].unpack(afi,safi,data,addpath,nexthop,action)
		raise Notify(3,0,'trying to decode unknown family %s/%s' % (AFI(afi),SAFI(safi)))
Ejemplo n.º 24
0
    def new(self, neighbor, restarted):
        graceful = neighbor.graceful_restart
        families = neighbor.families()

        mp = MultiProtocol()
        mp.extend(families)
        self[Capability.ID.MULTIPROTOCOL_EXTENSIONS] = mp

        if neighbor.asn4:
            self[Capability.ID.FOUR_BYTES_ASN] = ASN4(neighbor.local_as)

        if neighbor.add_path:
            ap_families = []
            if (AFI(AFI.ipv4), SAFI(SAFI.unicast)) in families:
                ap_families.append((AFI(AFI.ipv4), SAFI(SAFI.unicast)))
            if (AFI(AFI.ipv6), SAFI(SAFI.unicast)) in families:
                ap_families.append((AFI(AFI.ipv6), SAFI(SAFI.unicast)))
            # if (AFI(AFI.ipv4),SAFI(SAFI.nlri_mpls)) in families:
            # 	ap_families.append((AFI(AFI.ipv4),SAFI(SAFI.nlri_mpls)))
            #if (AFI(AFI.ipv6),SAFI(SAFI.unicast)) in families:
            #	ap_families.append((AFI(AFI.ipv6),SAFI(SAFI.unicast)))
            self[Capability.ID.ADD_PATH] = AddPath(ap_families,
                                                   neighbor.add_path)

        if graceful:
            if restarted:
                self[Capability.ID.GRACEFUL_RESTART] = Graceful().set(
                    Graceful.RESTART_STATE, graceful,
                    [(afi, safi, Graceful.FORWARDING_STATE)
                     for (afi, safi) in families])
            else:
                self[Capability.ID.GRACEFUL_RESTART] = Graceful().set(
                    0x0, graceful, [(afi, safi, Graceful.FORWARDING_STATE)
                                    for (afi, safi) in families])

        if neighbor.route_refresh:
            self[Capability.ID.ROUTE_REFRESH] = RouteRefresh()
            self[Capability.ID.ENHANCED_ROUTE_REFRESH] = EnhancedRouteRefresh()

        # MUST be the last key added
        if neighbor.multisession:
            self[Capability.ID.MULTISESSION_BGP] = MultiSession().set(
                [Capability.ID.MULTIPROTOCOL_EXTENSIONS])
        return self
Ejemplo n.º 25
0
	def post (self):
		route = self.scope.pop(self.name)

		# if route.nlri.has_rd(): # ???
		if route.nlri.rd is not RouteDistinguisher.NORD:
			route.nlri.safi = SAFI(SAFI.flow_vpn)

		if route:
			self.scope.append('routes',route)
		return True
Ejemplo n.º 26
0
	def unpack_capability (instance, data, capability=None):  # pylint: disable=W0613
		# XXX: FIXME: we should complain if we have twice the same AFI/SAFI
		# XXX: FIXME: should check that we have not yet seen the capability
		while data:
			afi = AFI.unpack(data[:2])
			safi = SAFI.unpack(data[3])
			nexthop = AFI.unpack(data[4:6])
			instance.add_nexthop(afi, safi, nexthop)
			data = data[6:]
		return instance
Ejemplo n.º 27
0
    def l2vpn(self, tokeniser):
        self._check_conflict()
        safi = tokeniser()

        if safi == 'vpls':
            self.content.append((AFI(AFI.l2vpn), SAFI(SAFI.vpls)))
        else:
            raise Raised('unknow family safi %s' % safi)

        self._drop_colon(tokeniser)
Ejemplo n.º 28
0
 def unpack_capability(instance, data, capability=None):  # pylint: disable=W0613
     # XXX: FIXME: we should complain if we have twice the same AFI/SAFI
     # XXX: FIXME: should check that we have not yet seen the capability
     while data:
         afi = AFI.unpack(data[:2])
         safi = SAFI.unpack(data[3])
         nexthop = AFI.unpack(data[4:6])
         instance.add_nexthop(afi, safi, nexthop)
         data = data[6:]
     return instance
Ejemplo n.º 29
0
	def unpack_nlri (cls, afi, safi, data, action, addpath):
		if not cls.logger:
			cls.logger = Logger()

		a,s = AFI.create(afi),SAFI.create(safi)
		cls.logger.debug(LazyNLRI(a,s,addpath,data),'parser')

		key = '%s/%s' % (a, s)
		if key in cls.registered_nlri:
			return cls.registered_nlri[key].unpack_nlri(a,s,data,action,addpath)
		raise Notify(3,0,'trying to decode unknown family %s/%s' % (a,s))
Ejemplo n.º 30
0
class OperationalFamily (Operational):
	def __init__ (self,what,afi,safi,data=''):
		self.afi = AFI(afi)
		self.safi = SAFI(afi)
		Operational.__init__(
			self,what,
			'%s%s%s' % (self.afi.pack(),self.safi.pack(),data)
		)

	def family (self):
		return (self.afi,self.safi)
Ejemplo n.º 31
0
 def register_nlri(klass):
     new = (AFI(afi), SAFI(safi))
     if new in cls.registered_nlri:
         if force:
             cls.registered_nlri['%d/%d' % new] = klass
         else:
             raise RuntimeError('Tried to register %s/%s twice' % new)
     else:
         cls.registered_nlri['%d/%d' % new] = klass
         cls.registered_families.append(new)
     return klass
Ejemplo n.º 32
0
    def _family(self, tokeniser, afi, safis, nhafis):
        safi = tokeniser().lower()
        if safi not in safis:
            raise ValueError('invalid afi/safi pair %s/%s' % (afi, safi))

        nhafi = tokeniser().lower()
        if nhafi not in nhafis:
            raise ValueError('invalid nexthop afi %s' % nhafi)

        seen = (AFI.fromString(afi), SAFI.fromString(safi), AFI.fromString(nhafi))
        self._seen.append(seen)
        return seen
Ejemplo n.º 33
0
	def _family (self, tokeniser, afi, safis, nhafis):
		safi = tokeniser().lower()
		if safi not in safis:
			raise ValueError('invalid afi/safi pair %s/%s' % (afi, safi))

		nhafi = tokeniser().lower()
		if nhafi not in nhafis:
			raise ValueError('invalid nexthop afi %s' % nhafi)

		seen = (AFI.fromString(afi), SAFI.fromString(safi), AFI.fromString(nhafi))
		self._seen.append(seen)
		return seen
Ejemplo n.º 34
0
	def _add (self,tokeniser,afi_name,safi_names):
		self._check_duplicate(tokeniser,RaisedFamily)
		known = self.content.setdefault(AFI(AFI.value(afi_name)),[])

		for (idx_line,idx_column,line,safi_name) in safi_names:
			if safi_name not in AFI.implemented_safi(afi_name):
				raise RaisedFamily(Location(idx_line,idx_column,line),'the family pair afi/safi %s/%s is unimplemented' % (afi_name,safi_name))

			safi = SAFI(SAFI.value(safi_name))
			if safi in known:
				raise RaisedFamily(Location(idx_line,idx_column,line),'afi/safi pair already defined in this family')
			known.append(safi)
Ejemplo n.º 35
0
Archivo: nlri.py Proyecto: cys3c/exabgp
		def register_nlri (klass):
			new = (AFI(afi),SAFI(safi))
			if new in cls.registered_nlri:
				if force:
					# python has a bug and does not allow %ld/%ld (pypy does)
					cls.registered_nlri['%s/%s' % new] = klass
				else:
					raise RuntimeError('Tried to register %s/%s twice' % new)
			else:
				# python has a bug and does not allow %ld/%ld (pypy does)
				cls.registered_nlri['%s/%s' % new] = klass
				cls.registered_families.append(new)
			return klass
Ejemplo n.º 36
0
		def register_nlri (klass):
			new = (AFI.create(afi),SAFI.create(safi))
			if new in cls.registered_nlri:
				if force:
					# python has a bug and does not allow %ld/%ld (pypy does)
					cls.registered_nlri['%s/%s' % new] = klass
				else:
					raise RuntimeError('Tried to register %s/%s twice' % new)
			else:
				# python has a bug and does not allow %ld/%ld (pypy does)
				cls.registered_nlri['%s/%s' % new] = klass
				cls.registered_families.append(new)
			return klass
Ejemplo n.º 37
0
class RouteRefresh(Message):
    ID = Message.CODE.ROUTE_REFRESH
    TYPE = character(Message.CODE.ROUTE_REFRESH)

    request = 0
    start = 1
    end = 2

    def __init__(self, afi, safi, reserved=0):
        self.afi = AFI(afi)
        self.safi = SAFI(safi)
        self.reserved = Reserved(reserved)

    def message(self, negotiated=None):
        return self._message(
            concat_bytes(self.afi.pack(), character(self.reserved),
                         self.safi.pack()))

    def __str__(self):
        return "REFRESH"

    def extensive(self):
        return 'route refresh %s/%d/%s' % (self.afi, self.reserved, self.safi)

    # XXX: Check how we get this data into the RR
    def families(self):
        return self._families[:]

    @classmethod
    def unpack_message(cls, data, _):
        try:
            afi, reserved, safi = unpack('!HBB', data)
        except error:
            raise Notify(7, 1, 'invalid route-refresh message')
        if reserved not in (0, 1, 2):
            raise Notify(7, 2, 'invalid route-refresh message subtype')
        return RouteRefresh(afi, safi, reserved)

    def __eq__(self, other):
        if not isinstance(other, RouteRefresh):
            return False
        if self.afi != other.afi:
            return False
        if self.safi != other.safi:
            return False
        if self.reserved != other.reserved:
            return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)
Ejemplo n.º 38
0
	def _addpath (self, neighbor):
		if not neighbor.add_path:
			return

		families = neighbor.families()
		ap_families = []
		if (AFI(AFI.ipv4),SAFI(SAFI.unicast)) in families:
			ap_families.append((AFI(AFI.ipv4),SAFI(SAFI.unicast)))
		if (AFI(AFI.ipv6),SAFI(SAFI.unicast)) in families:
			ap_families.append((AFI(AFI.ipv6),SAFI(SAFI.unicast)))
		if (AFI(AFI.ipv4),SAFI(SAFI.nlri_mpls)) in families:
			ap_families.append((AFI(AFI.ipv4),SAFI(SAFI.nlri_mpls)))
		if (AFI(AFI.ipv6),SAFI(SAFI.unicast)) in families:
			ap_families.append((AFI(AFI.ipv6),SAFI(SAFI.unicast)))
		self[Capability.CODE.ADD_PATH] = AddPath(ap_families,neighbor.add_path)
Ejemplo n.º 39
0
	def unpack (what,instance,data):
		# XXX: FIXME: should raise if instance was already setup
		restart = unpack('!H',data[:2])[0]
		restart_flag = restart >> 12
		restart_time = restart & Graceful.TIME_MASK
		data = data[2:]
		families = []
		while data:
			afi = AFI.unpack(data[:2])
			safi = SAFI.unpack(data[2])
			flag_family = ord(data[0])
			families.append((afi,safi,flag_family))
			data = data[4:]
		return instance.set(restart_flag,restart_time,families)
Ejemplo n.º 40
0
	def unpack_capability (instance, data, capability=None):  # pylint: disable=W0613
		# XXX: FIXME: should raise if instance was already setup
		restart = unpack('!H',data[:2])[0]
		restart_flag = restart >> 12
		restart_time = restart & Graceful.TIME_MASK
		data = data[2:]
		families = []
		while data:
			afi = AFI.unpack(data[:2])
			safi = SAFI.unpack(data[2])
			flag_family = ord(data[3])
			families.append((afi,safi,flag_family))
			data = data[4:]
		return instance.set(restart_flag,restart_time,families)
Ejemplo n.º 41
0
 def unpack_capability(instance, data, _=None):
     # XXX: FIXME: should raise if instance was already setup
     restart = unpack('!H', data[:2])[0]
     restart_flag = restart >> 12
     restart_time = restart & Graceful.TIME_MASK
     data = data[2:]
     families = []
     while data:
         afi = AFI.unpack(data[:2])
         safi = SAFI.unpack(data[2])
         flag_family = ord(data[0])
         families.append((afi, safi, flag_family))
         data = data[4:]
     return instance.set(restart_flag, restart_time, families)
Ejemplo n.º 42
0
class RouteRefresh (Message):
	ID = Message.CODE.ROUTE_REFRESH
	TYPE = chr(Message.CODE.ROUTE_REFRESH)

	request = 0
	start = 1
	end = 2

	def __init__ (self, afi, safi, reserved=0):
		self.afi = AFI(afi)
		self.safi = SAFI(safi)
		self.reserved = Reserved(reserved)

	def message (self,negotiated=None):
		return self._message('%s%s%s' % (self.afi.pack(),chr(self.reserved),self.safi.pack()))

	def __str__ (self):
		return "REFRESH"

	def extensive (self):
		return 'route refresh %s/%d/%s' % (self.afi,self.reserved,self.safi)

	def families (self):
		return self._families[:]

	@classmethod
	def unpack_message (cls, data, _):
		try:
			afi,reserved,safi = unpack('!HBB',data)
		except error:
			raise Notify(7,1,'invalid route-refresh message')
		if reserved not in (0,1,2):
			raise Notify(7,2,'invalid route-refresh message subtype')
		return RouteRefresh(afi,safi,reserved)

	def __eq__ (self, other):
		if not isinstance(other, RouteRefresh):
			return False
		if self.afi != other.afi:
			return False
		if self.safi != other.safi:
			return False
		if self.reserved != other.reserved:
			return False
		return True

	def __ne__ (self, other):
		return not self.__eq__(other)
Ejemplo n.º 43
0
	def parse_api_eor (self,command):
		tokens = formated(command).split(' ')[2:]
		lt = len(tokens)

		if not lt:
			return Family(1,1)

		if lt !=2:
			return False

		afi = AFI.fromString(tokens[0])
		if afi == AFI.undefined:
			return False

		safi = SAFI.fromString(tokens[1])
		if safi == SAFI.undefined:
			return False

		return Family(afi,safi)
Ejemplo n.º 44
0
	def api_eor (self, command):
		tokens = formated(command).split(' ')[2:]
		number = len(tokens)

		if not number:
			return Family(1,1)

		if number != 2:
			return False

		afi = AFI.fromString(tokens[0])
		if afi == AFI.undefined:
			return False

		safi = SAFI.fromString(tokens[1])
		if safi == SAFI.undefined:
			return False

		return Family(afi,safi)
Ejemplo n.º 45
0
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		afi,safi = unpack('!HB',data[:3])
		offset = 3
		data = data[offset:]

		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %s %s' % (AFI.create(afi),SAFI.create(safi)))

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		while data:
			nlri,data = NLRI.unpack_nlri(afi,safi,data,IN.WITHDRAWN,addpath)
			nlris.append(nlri)

		return cls(afi,safi,nlris)
Ejemplo n.º 46
0
class OperationalFamily (Operational):
	has_family = True

	def __init__ (self,what,afi,safi,data=''):
		Operational.__init__(self,what)
		self.afi = AFI(afi)
		self.safi = SAFI(afi)
		self.data = data

	def family (self):
		return (self.afi,self.safi)

	def _message (self,data):
		return Operational._message(self,"%s%s%s" % (
			self.afi.pack(),
			self.safi.pack(),
			data
		))

	def message (self,negotiated):
		return self._message(self.data)
Ejemplo n.º 47
0
class RouteRefresh (Message):
	TYPE = chr(Message.Type.ROUTE_REFRESH)

	request = 0
	start = 1
	end = 2

	def __init__ (self,afi,safi,reserved=0):
		self.afi = AFI(afi)
		self.safi = SAFI(safi)
		self.reserved = Reserved(reserved)

	def messages (self,negotitated):
		return [self._message('%s%s%s' % (self.afi.pack(),chr(self.reserved),self.safi.pack())),]

	def __str__ (self):
		return "REFRESH"

	def extensive (self):
		return 'route refresh %s/%d/%s' % (self.afi,self.reserved,self.safi)

	def families (self):
		return self._families[:]
Ejemplo n.º 48
0
	def __init__ (self, afi, safi, reserved=0):
		self.afi = AFI(afi)
		self.safi = SAFI(safi)
		self.reserved = Reserved(reserved)
Ejemplo n.º 49
0
	def unpack_capability (instance, data, capability=None):  # pylint: disable=W0613
		# XXX: FIXME: we should raise if we have twice the same AFI/SAFI
		afi = AFI.unpack(data[:2])
		safi = SAFI.unpack(data[3])
		instance.append((afi,safi))
		return instance
Ejemplo n.º 50
0
	def unpack_message (cls, data, negotiated):
		header_length = len(EOR.NLRI.PREFIX)
		return cls(AFI.unpack(data[header_length:header_length+2]),SAFI.unpack(data[header_length+2]))
Ejemplo n.º 51
0
	def unpack (what,instance,data):
		# XXX: FIXME: we should raise if we have twice the same AFI/SAFI
		afi = AFI.unpack(data[:2])
		safi = SAFI.unpack(data[3])
		instance.append((afi,safi))
		return instance
Ejemplo n.º 52
0
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		_afi,_safi = unpack('!HB',data[:3])
		afi,safi = AFI.create(_afi),SAFI.create(_safi)
		offset = 3

		# we do not want to accept unknown families
		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %s/%s' % (afi,safi))

		# -- Reading length of next-hop
		len_nh = ordinal(data[offset])
		offset += 1

		if (afi,safi) not in Family.size:
			raise Notify(3,0,'unsupported %s %s' % (afi,safi))

		length,rd = Family.size[(afi,safi)]

		if len_nh not in length:
			raise Notify(3,0,'invalid %s %s next-hop length %d expected %s' % (afi,safi,len_nh,' or '.join(str(_) for _ in length)))

		size = len_nh - rd

		# XXX: FIXME: GET IT FROM CACHE HERE ?
		nhs = data[offset+rd:offset+rd+size]
		nexthops = [nhs[pos:pos+16] for pos in range(0,len(nhs),16)]

		# chech the RD is well zero
		if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0:
			raise Notify(3,0,"MP_REACH_NLRI next-hop's route-distinguisher must be zero")

		offset += len_nh

		# Skip a reserved bit as somone had to bug us !
		reserved = ordinal(data[offset])
		offset += 1

		if reserved != 0:
			raise Notify(3,0,'the reserved bit of MP_REACH_NLRI is not zero')

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		# Reading the NLRIs
		data = data[offset:]

		if not data:
			raise Notify(3,0,'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi,safi))

		while data:
			if nexthops:
				for nexthop in nexthops:
					nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
					nlri.nexthop = NextHop.unpack(nexthop)
					nlris.append(nlri)
			else:
				nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
				nlris.append(nlri)

			if left == data:
				raise RuntimeError("sub-calls should consume data")

			data = left
		return cls(afi,safi,nlris)
Ejemplo n.º 53
0
	def __init__ (self, what, afi, safi, data=b''):
		Operational.__init__(self,what)
		self.afi = AFI.create(afi)
		self.safi = SAFI.create(safi)
		self.data = data
Ejemplo n.º 54
0
	def __init__ (self,what,afi,safi,data=''):
		Operational.__init__(self,what)
		self.afi = AFI(afi)
		self.safi = SAFI(afi)
		self.data = data