Example #1
0
	def test_decoding_udpate_asn4 (self):
		try:
			for asn4,body in bodies:
				if not asn4: continue
				Update.unpack_message(''.join(chr(_) for _ in body),self.negotiated[asn4])
		except Notify:
			self.assertEqual(1,0)
Example #2
0
def check_update (neighbor, raw):
	from exabgp.logger import Logger

	logger = Logger()
	logger._parser = True
	logger.parser('\ndecoding routes in configuration')

	n = neighbor[neighbor.keys()[0]]
	p = Peer(n,None)

	path = {}
	for f in known_families():
		if n.add_path:
			path[f] = n.add_path

	capa = Capabilities().new(n,False)
	capa[Capability.CODE.ADD_PATH] = path
	capa[Capability.CODE.MULTIPROTOCOL] = n.families()

	routerid_1 = str(n.router_id)
	routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(n.router_id).split('.',-1))

	o1 = Open(4,n.local_as,routerid_1,capa,180)
	o2 = Open(4,n.peer_as,routerid_2,capa,180)
	negotiated = Negotiated(n)
	negotiated.sent(o1)
	negotiated.received(o2)
	# grouped = False

	while raw:
		if raw.startswith('\xff'*16):
			kind = ord(raw[18])
			size = (ord(raw[16]) << 16) + (ord(raw[17]))

			injected,raw = raw[19:size],raw[size:]

			if kind == 2:
				logger.parser('the message is an update')
				decoding = 'update'
			else:
				logger.parser('the message is not an update (%d) - aborting' % kind)
				return False
		else:
			logger.parser('header missing, assuming this message is ONE update')
			decoding = 'update'
			injected,raw = raw,''

		try:
			# This does not take the BGP header - let's assume we will not break that :)
			update = Update.unpack_message(injected,negotiated)
		except KeyboardInterrupt:
			raise
		except Notify,exc:
			logger.parser('could not parse the message','error')
			logger.parser(str(exc),'error')
			return False
		except Exception,exc:
			logger.parser('could not parse the message','error')
			logger.parser(str(exc),'error')
			return False
Example #3
0
def check_update (neighbor, raw):
	from exabgp.logger import Logger

	logger = Logger()
	logger._parser = True
	logger.parser('\ndecoding routes in configuration')

	n = neighbor[neighbor.keys()[0]]
	p = Peer(n,None)

	path = {}
	for f in known_families():
		if n.add_path:
			path[f] = n.add_path

	capa = Capabilities().new(n,False)
	capa[Capability.CODE.ADD_PATH] = path
	capa[Capability.CODE.MULTIPROTOCOL] = n.families()

	routerid_1 = str(n.router_id)
	routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(n.router_id).split('.',-1))

	o1 = Open(4,n.local_as,routerid_1,capa,180)
	o2 = Open(4,n.peer_as,routerid_2,capa,180)
	negotiated = Negotiated(n)
	negotiated.sent(o1)
	negotiated.received(o2)
	# grouped = False

	while raw:
		if raw.startswith('\xff'*16):
			kind = ord(raw[18])
			size = (ord(raw[16]) << 16) + (ord(raw[17]))

			injected,raw = raw[19:size],raw[size:]

			if kind == 2:
				logger.parser('the message is an update')
				decoding = 'update'
			else:
				logger.parser('the message is not an update (%d) - aborting' % kind)
				return False
		else:
			logger.parser('header missing, assuming this message is ONE update')
			decoding = 'update'
			injected,raw = raw,''

		try:
			# This does not take the BGP header - let's assume we will not break that :)
			update = Update.unpack_message(injected,negotiated)
		except KeyboardInterrupt:
			raise
		except Notify,exc:
			logger.parser('could not parse the message')
			logger.parser(str(exc))
			return False
		except Exception,exc:
			logger.parser('could not parse the message')
			logger.parser(str(exc))
			return False
Example #4
0
    def send(self, raw):
        if self.neighbor.api.get('send-%d' % ord(raw[19]), False):
            message = Update.unpack_message(raw[19:], self.negotiated)
            self._to_api('send', message, raw)

        for boolean in self.connection.writer(raw):
            yield boolean
Example #5
0
	def send (self,raw):
		if self.neighbor.api.get('send-%d' % ord(raw[19]),False):
			message = Update.unpack_message(raw[19:],self.negotiated)
			self._to_api('send',message,raw)

		for boolean in self.connection.writer(raw):
			yield boolean
Example #6
0
def check_update(neighbor, raw):
    from exabgp.logger import Logger

    logger = Logger()
    logger._parser = True
    logger.parser("\ndecoding routes in configuration")

    n = neighbor[neighbor.keys()[0]]
    p = Peer(n, None)

    path = {}
    for f in known_families():
        if n.add_path:
            path[f] = n.add_path

    capa = Capabilities().new(n, False)
    capa[Capability.ID.ADD_PATH] = path
    capa[Capability.ID.MULTIPROTOCOL_EXTENSIONS] = n.families()

    o1 = Open(4, n.local_as, str(n.local_address), capa, 180)
    o2 = Open(4, n.peer_as, str(n.peer_address), capa, 180)
    negotiated = Negotiated(n)
    negotiated.sent(o1)
    negotiated.received(o2)
    # grouped = False

    while raw:
        if raw.startswith("\xff" * 16):
            kind = ord(raw[18])
            size = (ord(raw[16]) << 16) + (ord(raw[17]))

            injected, raw = raw[19:size], raw[size:]

            if kind == 2:
                logger.parser("the message is an update")
                decoding = "update"
            else:
                logger.parser("the message is not an update (%d) - aborting" % kind)
                return False
        else:
            logger.parser("header missing, assuming this message is ONE update")
            decoding = "update"
            injected, raw = raw, ""

        try:
            # This does not take the BGP header - let's assume we will not break that :)
            update = Update.unpack_message(injected, negotiated)
        except KeyboardInterrupt:
            raise
        except Notify, e:
            logger.parser("could not parse the message")
            logger.parser(str(e))
            return False
        except Exception, e:
            logger.parser("could not parse the message")
            logger.parser(str(e))
            return False
Example #7
0
File: bmp.py Project: xw2060/exabgp
    def _route(self, header):
        bgp_header = self._read_data(19)
        if bgp_header is None:
            self.close()
            return
        length = unpack('!H', bgp_header[16:18])[0] - 19
        bgp_body = self._read_data(length)
        if bgp_body is None:
            self.close()
            return

        negotiated = FakeNegotiated(header, self.asn4)
        update = Update.unpack_message(bgp_body, negotiated)
        if self.use_json:
            print >> self.fd, self.json.bmp(self.ip, update)
        else:
            for route in update.routes:
                print >> self.fd, route.extensive()
Example #8
0
File: bmp.py Project: fobser/exabgp
	def _route (self, header):
		bgp_header = self._read_data(19)
		if bgp_header is None:
			self.close()
			return
		length = unpack('!H',bgp_header[16:18])[0] - 19
		bgp_body = self._read_data(length)
		if bgp_body is None:
			self.close()
			return

		negotiated = FakeNegotiated(header,self.asn4)
		update = Update.unpack_message(bgp_body,negotiated)
		if self.use_json:
			print >> self.fd, self.json.bmp(self.ip,update)
		else:
			for route in update.routes:
				print >> self.fd, route.extensive()
Example #9
0
def check_neighbor (neighbors):
	from exabgp.logger import Logger

	logger = Logger()
	logger._option.parser = True

	if not neighbors:
		logger.parser('\ncould not find neighbor(s) to check')
		return False

	logger.parser('\ndecoding routes in configuration')

	for name in neighbors.keys():
		neighbor = neighbors[name]

		path = {}
		for f in known_families():
			if neighbor.add_path:
				path[f] = neighbor.add_path

		capa = Capabilities().new(neighbor,False)
		if path:
			capa[Capability.CODE.ADD_PATH] = path
		capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()

		o1 = Open(4,neighbor.local_as,'127.0.0.2',capa,180)
		o2 = Open(4,neighbor.peer_as,'127.0.0.3',capa,180)
		negotiated = Negotiated(neighbor)
		negotiated.sent(o1)
		negotiated.received(o2)
		# grouped = False

		for message in neighbor.rib.outgoing.updates(False):
			pass

		for change1 in neighbor.rib.outgoing.sent_changes():
			str1 = change1.extensive()
			packed = list(Update([change1.nlri],change1.attributes).messages(negotiated))
			pack1 = packed[0]

			logger.parser('parsed route requires %d updates' % len(packed))
			logger.parser('parsed route requires %d updates' % len(packed))
			logger.parser('update size is %d' % len(pack1))

			logger.parser('parsed route %s' % str1)
			logger.parser('parsed hex   %s' % od(pack1))

			# This does not take the BGP header - let's assume we will not break that :)
			try:
				logger.parser('')  # new line

				pack1s = pack1[19:] if pack1.startswith('\xFF'*16) else pack1
				update = Update.unpack_message(pack1s,negotiated)

				change2 = Change(update.nlris[0],update.attributes)
				str2 = change2.extensive()
				pack2 = list(Update([update.nlris[0]],update.attributes).messages(negotiated))[0]

				logger.parser('recoded route %s' % str2)
				logger.parser('recoded hex   %s' % od(pack2))

				str1r = str1.replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','')
				str2r = str2.replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','')

				if ' name ' in str1r:
					parts = str1r.split(' ')
					pos = parts.index('name')
					str1r = ' '.join(parts[:pos] + parts[pos+2:])

				skip = False

				if str1r != str2r:
					if 'attribute [' in str1r and ' 0x00 ' in str1r:
						# we do not decode non-transitive attributes
						logger.parser('skipping string check on update with non-transitive attribute(s)')
						skip = True
					else:
						logger.parser('strings are different:')
						logger.parser('[%s]' % (str1r))
						logger.parser('[%s]' % (str2r))
						return False
				else:
					logger.parser('strings are fine')

				if skip:
					logger.parser('skipping encoding for update with non-transitive attribute(s)')
				elif pack1 != pack2:
					logger.parser('encoding are different')
					logger.parser('[%s]' % (od(pack1)))
					logger.parser('[%s]' % (od(pack2)))
					return False
				else:
					logger.parser('encoding is fine')
					logger.parser('----------------------------------------')

				logger.parser('JSON nlri %s' % change1.nlri.json())
				logger.parser('JSON attr %s' % change1.attributes.json())

			except Notify,exc:
				logger.parser('----------------------------------------')
				logger.parser(str(exc))
				logger.parser('----------------------------------------')
				return False
		neighbor.rib.clear()
Example #10
0
from exabgp.bgp.message.keepalive import new_KeepAlive
from exabgp.bgp.message.update import Update
from exabgp.bgp.message.update import Attributes

from exabgp.rib.table import Table
from exabgp.rib.delta import Delta
from exabgp.reactor.protocol import Protocol
from exabgp.bgp.neighbor import Neighbor

from StringIO import StringIO

class Network (StringIO):
	def pending (self):
		return True

route1 = Update([],[to_NLRI('10.0.0.1','32')],Attributes())
route1.next_hop = '10.0.0.254'

route2 = Update([],[to_NLRI('10.0.1.1','32')],Attributes())
route2.next_hop = '10.0.0.254'

route3 = Update([],[to_NLRI('10.0.2.1','32')],Attributes())
route3.next_hop = '10.0.0.254'

routes = [route1,route2,route3]
routes.sort()

class TestProtocol (unittest.TestCase):

	def setUp(self):
		self.table = Table()
Example #11
0
def check_neighbor(neighbor):
    from exabgp.logger import Logger

    logger = Logger()
    logger._parser = True
    logger.parser('\ndecoding routes in configuration')

    n = neighbor[neighbor.keys()[0]]

    path = {}
    for f in known_families():
        if n.add_path:
            path[f] = n.add_path

    capa = Capabilities().new(n, False)
    capa[Capability.ID.ADD_PATH] = path
    capa[Capability.ID.MULTIPROTOCOL] = n.families()

    o1 = Open(4, n.local_as, str(n.local_address), capa, 180)
    o2 = Open(4, n.peer_as, str(n.peer_address), capa, 180)
    negotiated = Negotiated(n)
    negotiated.sent(o1)
    negotiated.received(o2)
    #grouped = False

    for nei in neighbor.keys():
        for message in neighbor[nei].rib.outgoing.updates(False):
            pass

        for change1 in neighbor[nei].rib.outgoing.sent_changes():
            str1 = change1.extensive()
            packed = list(
                Update([change1.nlri],
                       change1.attributes).messages(negotiated))
            pack1 = packed[0]

            logger.parser('parsed route requires %d updates' % len(packed))
            logger.parser('update size is %d' % len(pack1))

            logger.parser('parsed route %s' % str1)
            logger.parser('parsed hex   %s' % od(pack1))

            # This does not take the BGP header - let's assume we will not break that :)
            try:
                logger.parser('')  # new line

                pack1s = pack1[19:] if pack1.startswith('\xFF' * 16) else pack1
                update = Update.unpack_message(pack1s, negotiated)

                change2 = Change(update.nlris[0], update.attributes)
                str2 = change2.extensive()
                pack2 = list(
                    Update([update.nlris[0]],
                           update.attributes).messages(negotiated))[0]

                logger.parser('recoded route %s' % str2)
                logger.parser('recoded hex   %s' % od(pack2))

                str1r = str1.replace(' med 100', '').replace(
                    ' local-preference 100', '').replace(' origin igp', '')
                str2r = str2.replace(' med 100', '').replace(
                    ' local-preference 100', '').replace(' origin igp', '')

                skip = False

                if str1r != str2r:
                    if 'attribute [' in str1r and ' 0x00 ' in str1r:
                        # we do not decode non-transitive attributes
                        logger.parser(
                            'skipping string check on update with non-transitive attribute(s)'
                        )
                        skip = True
                    else:
                        logger.parser('strings are different:')
                        logger.parser('[%s]' % str1r)
                        logger.parser('[%s]' % str2r)
                        return False
                else:
                    logger.parser('strings are fine')

                if skip:
                    logger.parser(
                        'skipping encoding for update with non-transitive attribute(s)'
                    )
                elif pack1 != pack2:
                    logger.parser('encoding are different')
                    logger.parser('[%s]' % od(pack1))
                    logger.parser('[%s]' % od(pack2))
                    return False
                else:
                    logger.parser('encoding is fine')
                    logger.parser('----------------------------------------')

            except Notify, e:
                logger.parser('----------------------------------------')
                logger.parser(str(e))
                logger.parser('----------------------------------------')
                return False
Example #12
0
def UpdateFactory(negotiated, data):
    logger = Logger()

    length = len(data)

    lw, withdrawn, data = defix(data)

    if len(withdrawn) != lw:
        raise Notify(
            3, 1, 'invalid withdrawn routes length, not enough data available')

    la, attribute, announced = defix(data)

    if len(attribute) != la:
        raise Notify(
            3, 1,
            'invalid total path attribute length, not enough data available')

    if 2 + lw + 2 + la + len(announced) != length:
        raise Notify(
            3, 1,
            'error in BGP message length, not enough data for the size announced'
        )

    attributes = AttributesFactory(NLRIFactory, negotiated, attribute)

    # Is the peer going to send us some Path Information with the route (AddPath)
    addpath = negotiated.addpath.receive(AFI(AFI.ipv4), SAFI(SAFI.unicast))
    nho = attributes.get(AID.NEXT_HOP, None)
    nh = nho.packed if nho else None

    if not withdrawn:
        logger.parser(LazyFormat("parsed no withdraw nlri", od, ''))

    nlris = []
    while withdrawn:
        length, nlri = NLRIFactory(AFI.ipv4, SAFI.unicast_multicast, withdrawn,
                                   addpath, nh, IN.withdrawn)
        logger.parser(
            LazyFormat("parsed withdraw nlri %s payload " % nlri, od,
                       withdrawn[:len(nlri)]))
        withdrawn = withdrawn[length:]
        nlris.append(nlri)

    if not announced:
        logger.parser(LazyFormat("parsed no announced nlri", od, ''))

    while announced:
        length, nlri = NLRIFactory(AFI.ipv4, SAFI.unicast_multicast, announced,
                                   addpath, nh, IN.announced)
        logger.parser(
            LazyFormat("parsed announce nlri %s payload " % nlri, od,
                       announced[:len(nlri)]))
        announced = announced[length:]
        nlris.append(nlri)

    for nlri in attributes.mp_withdraw:
        nlris.append(nlri)

    for nlri in attributes.mp_announce:
        nlris.append(nlri)

    return Update(nlris, attributes)
Example #13
0
	def test_decoding_udpate_asn4 (self):
		for asn4,body in bodies:
			if not asn4:
				continue
			Update.unpack_message(''.join(chr(_) for _ in body),self.negotiated[asn4])
Example #14
0
def check_neighbor(neighbor):
    from exabgp.logger import Logger

    logger = Logger()
    logger._parser = True
    logger.parser("\ndecoding routes in configuration")

    n = neighbor[neighbor.keys()[0]]

    path = {}
    for f in known_families():
        if n.add_path:
            path[f] = n.add_path

    capa = Capabilities().new(n, False)
    capa[Capability.ID.ADD_PATH] = path
    capa[Capability.ID.MULTIPROTOCOL_EXTENSIONS] = n.families()

    o1 = Open(4, n.local_as, str(n.local_address), capa, 180)
    o2 = Open(4, n.peer_as, str(n.peer_address), capa, 180)
    negotiated = Negotiated(n)
    negotiated.sent(o1)
    negotiated.received(o2)
    # grouped = False

    for nei in neighbor.keys():
        for message in neighbor[nei].rib.outgoing.updates(False):
            pass

        for change1 in neighbor[nei].rib.outgoing.sent_changes():
            str1 = change1.extensive()
            packed = list(Update([change1.nlri], change1.attributes).messages(negotiated))
            pack1 = packed[0]

            logger.parser("parsed route requires %d updates" % len(packed))
            logger.parser("update size is %d" % len(pack1))

            logger.parser("parsed route %s" % str1)
            logger.parser("parsed hex   %s" % od(pack1))

            # This does not take the BGP header - let's assume we will not break that :)
            try:
                logger.parser("")  # new line

                pack1s = pack1[19:] if pack1.startswith("\xFF" * 16) else pack1
                update = Update.unpack_message(pack1s, negotiated)

                change2 = Change(update.nlris[0], update.attributes)
                str2 = change2.extensive()
                pack2 = list(Update([update.nlris[0]], update.attributes).messages(negotiated))[0]

                logger.parser("recoded route %s" % str2)
                logger.parser("recoded hex   %s" % od(pack2))

                str1r = str1.replace(" med 100", "").replace(" local-preference 100", "").replace(" origin igp", "")
                str2r = str2.replace(" med 100", "").replace(" local-preference 100", "").replace(" origin igp", "")

                skip = False

                if str1r != str2r:
                    if "attribute [" in str1r and " 0x00 " in str1r:
                        # we do not decode non-transitive attributes
                        logger.parser("skipping string check on update with non-transitive attribute(s)")
                        skip = True
                    else:
                        logger.parser("strings are different:")
                        logger.parser("[%s]" % str1r)
                        logger.parser("[%s]" % str2r)
                        return False
                else:
                    logger.parser("strings are fine")

                if skip:
                    logger.parser("skipping encoding for update with non-transitive attribute(s)")
                elif pack1 != pack2:
                    logger.parser("encoding are different")
                    logger.parser("[%s]" % od(pack1))
                    logger.parser("[%s]" % od(pack2))
                    return False
                else:
                    logger.parser("encoding is fine")
                    logger.parser("----------------------------------------")

            except Notify, e:
                logger.parser("----------------------------------------")
                logger.parser(str(e))
                logger.parser("----------------------------------------")
                return False
Example #15
0
from exabgp.bgp.message.update import Update
from exabgp.bgp.message.update import Attributes
from exabgp.bgp.message.update import new_Update

from exabgp.reactor.protocol import Protocol
from exabgp.bgp.neighbor import Neighbor

from StringIO import StringIO


class Network(StringIO):
    def pending(self):
        return True


route1 = Update([], [to_NLRI("10.0.0.1", "32")], Attributes())
route1.next_hop = "10.0.0.254"

route2 = Update([], [to_NLRI("10.0.1.1", "32")], Attributes())
route2.next_hop = "10.0.0.254"

route3 = Update([], [to_NLRI("10.0.2.1", "32")], Attributes())
route3.next_hop = "10.0.0.254"

routes = [route1, route2, route3]
routes.sort()


class TestProtocol(unittest.TestCase):
    def setUp(self):
        self.neighbor = Neighbor()
Example #16
0
 def test_decoding_udpate_asn4(self):
     for asn4, body in bodies:
         if not asn4: continue
         Update.unpack_message(''.join(chr(_) for _ in body),
                               self.negotiated[asn4])
Example #17
0
from exabgp.bgp.message.update import Update
from exabgp.bgp.message.update import EOR
from exabgp.bgp.message.keepalive import KeepAlive
from exabgp.bgp.message.notification import Notification
from exabgp.bgp.message.notification import Notify
from exabgp.bgp.message.operational import Operational

from exabgp.reactor.api.processes import ProcessError

from exabgp.logger import Logger
from exabgp.logger import FakeLogger

# This is the number of chuncked message we are willing to buffer, not the number of routes
MAX_BACKLOG = 15000

_UPDATE = Update([], '')
_OPERATIONAL = Operational(0x00)


class Protocol(object):
    decode = True

    def __init__(self, peer):
        try:
            self.logger = Logger()
        except RuntimeError:
            self.logger = FakeLogger()
        self.peer = peer
        self.neighbor = peer.neighbor
        self.negotiated = Negotiated(self.neighbor)
        self.connection = None
Example #18
0
	def updates (self,grouped):
		if self._changes:
			dict_nlri = self._modify_nlri

			for family in self._seen:
				for change in self._seen[family].itervalues():
					if change.index() not in self._modify_nlri:
						change.nlri.action = OUT.WITHDRAW
						self.insert_announced(change,True)

			for new in self._changes:
				self.insert_announced(new,True)
			self._changes = None
		# end of changes

		rr_announced = []

		for afi,safi in self._enhanced_refresh_start:
			rr_announced.append((afi,safi))
			yield RouteRefresh(afi,safi,RouteRefresh.start)

		dict_sorted = self._modify_sorted
		dict_nlri = self._modify_nlri
		dict_attr = self._cache_attribute

		for attr_index,full_dict_change in dict_sorted.items():
			if self.cache:
				dict_change = {}
				for nlri_index,change in full_dict_change.iteritems():
					family = change.nlri.family()
					announced = self._seen.get(family,{})
					if change.nlri.action == OUT.ANNOUNCE:
						if nlri_index in announced:
							old_change = announced[nlri_index]
							# it is a duplicate route
							if old_change.attributes.index() == change.attributes.index():
								continue
					elif change.nlri.action == OUT.WITHDRAW:
						if nlri_index not in announced:
							if dict_nlri[nlri_index].nlri.action == OUT.ANNOUNCE:
								continue
					dict_change[nlri_index] = change
			else:
				dict_change = full_dict_change

			if not dict_change:
				continue

			attributes = dict_attr[attr_index].attributes

			# we NEED the copy provided by list() here as insert_announced can be called while we iterate
			changed = list(dict_change.itervalues())

			if grouped:
				update = Update([dict_nlri[nlri_index].nlri for nlri_index in dict_change],attributes)
				for change in changed:
					nlri_index = change.index()
					del dict_sorted[attr_index][nlri_index]
					del dict_nlri[nlri_index]
				# only yield once we have a consistent state, otherwise it will go wrong
				# as we will try to modify things we are using
				yield update
			else:
				updates = []
				for change in changed:
					updates.append(Update([change.nlri,],attributes))
					nlri_index = change.index()
					del dict_sorted[attr_index][nlri_index]
					del dict_nlri[nlri_index]
				# only yield once we have a consistent state, otherwise it will go wrong
				# as we will try to modify things we are using
				for update in updates:
					yield update

			if self.cache:
				announced = self._seen
				for change in changed:
					if change.nlri.action == OUT.ANNOUNCE:
						announced.setdefault(change.nlri.family(),{})[change.index()] = change
					else:
						family = change.nlri.family()
						if family in announced:
							announced[family].pop(change.index(),None)

		if rr_announced:
			for afi,safi in rr_announced:
				self._enhanced_refresh_start.remove((afi,safi))
				yield RouteRefresh(afi,safi,RouteRefresh.end)

			for change in self._enhanced_refresh_delay:
				self.insert_announced(change,True)
			self.enhanced_refresh_delay = []

			for update in self.updates(grouped):
				yield update
Example #19
0
def check_neighbor (neighbors):
	from exabgp.logger import Logger

	logger = Logger()
	logger._parser = True

	if not neighbors:
		logger.parser('\ncould not find neighbor(s) to check')
		return False

	logger.parser('\ndecoding routes in configuration')

	for name in neighbors.keys():
		neighbor = neighbors[name]
		neighbor.rib.clear()

		path = {}
		for f in known_families():
			if neighbor.add_path:
				path[f] = neighbor.add_path

		capa = Capabilities().new(neighbor,False)
		capa[Capability.CODE.ADD_PATH] = path
		capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()

		o1 = Open(4,neighbor.local_as,str(neighbor.local_address),capa,180)
		o2 = Open(4,neighbor.peer_as,str(neighbor.peer_address),capa,180)
		negotiated = Negotiated(neighbor)
		negotiated.sent(o1)
		negotiated.received(o2)
		# grouped = False

		for message in neighbor.rib.outgoing.updates(False):
			pass

		for change1 in neighbor.rib.outgoing.sent_changes():
			str1 = change1.extensive()
			packed = list(Update([change1.nlri],change1.attributes).messages(negotiated))
			pack1 = packed[0]

			logger.parser('parsed route requires %d updates' % len(packed))
			logger.parser('update size is %d' % len(pack1))

			logger.parser('parsed route %s' % str1)
			logger.parser('parsed hex   %s' % od(pack1))

			# This does not take the BGP header - let's assume we will not break that :)
			try:
				logger.parser('')  # new line

				pack1s = pack1[19:] if pack1.startswith('\xFF'*16) else pack1
				update = Update.unpack_message(pack1s,negotiated)

				change2 = Change(update.nlris[0],update.attributes)
				str2 = change2.extensive()
				pack2 = list(Update([update.nlris[0]],update.attributes).messages(negotiated))[0]

				logger.parser('recoded route %s' % str2)
				logger.parser('recoded hex   %s' % od(pack2))

				str1r = str1.replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','')
				str2r = str2.replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','')

				if ' name ' in str1r:
					parts = str1r.split(' ')
					pos = parts.index('name')
					str1r = ' '.join(parts[:pos] + parts[pos+2:])

				skip = False

				if str1r != str2r:
					if 'attribute [' in str1r and ' 0x00 ' in str1r:
						# we do not decode non-transitive attributes
						logger.parser('skipping string check on update with non-transitive attribute(s)')
						skip = True
					else:
						logger.parser('strings are different:')
						logger.parser('[%s]' % (str1r))
						logger.parser('[%s]' % (str2r))
						return False
				else:
						logger.parser('strings are fine')

				if skip:
					logger.parser('skipping encoding for update with non-transitive attribute(s)')
				elif pack1 != pack2:
					logger.parser('encoding are different')
					logger.parser('[%s]' % (od(pack1)))
					logger.parser('[%s]' % (od(pack2)))
					return False
				else:
					logger.parser('encoding is fine')
					logger.parser('----------------------------------------')

			except Notify,exc:
				logger.parser('----------------------------------------')
				logger.parser(str(exc))
				logger.parser('----------------------------------------')
				return False
Example #20
0
    def updates(self, grouped):
        dict_sorted = self._modify_sorted
        dict_nlri = self._modify_nlri
        dict_attr = self._cache_attribute

        for attr_index, full_dict_change in list(dict_sorted.iteritems()):
            if self.cache:
                dict_change = {}
                for nlri_index, change in full_dict_change.iteritems():
                    family = change.nlri.family()
                    announced = self._announced.get(family, {})
                    if change.nlri.action == OUT.announce:
                        if nlri_index in announced:
                            old_change = announced[nlri_index]
                            # it is a duplicate route
                            if old_change.attributes.index(
                            ) == change.attributes.index():
                                continue
                    elif change.nlri.action == OUT.withdraw:
                        if nlri_index not in announced:
                            continue
                    dict_change[nlri_index] = change
            else:
                dict_change = full_dict_change

            if not dict_change:
                continue

            attributes = dict_attr[attr_index].attributes

            # we NEED the copy provided by list() here as clear_sent or insert_announced can be called while we iterate
            changed = list(dict_change.itervalues())

            if grouped:
                update = Update(
                    [dict_nlri[nlri_index].nlri for nlri_index in dict_change],
                    attributes)
                for change in changed:
                    nlri_index = change.nlri.index()
                    del dict_change[nlri_index]
                    del dict_nlri[nlri_index]
                # only yield once we have a consistent state, otherwise it will go wrong
                # as we will try to modify things we are using
                yield update
            else:
                updates = [
                    Update([
                        change.nlri,
                    ], attributes) for change in changed
                ]
                for change in changed:
                    nlri_index = change.nlri.index()
                    del dict_change[nlri_index]
                    del dict_nlri[nlri_index]
                # only yield once we have a consistent state, otherwise it will go wrong
                # as we will try to modify things we are using
                for update in updates:
                    yield update

            if self.cache:
                announced = self._announced
                for change in changed:
                    if change.nlri.action == OUT.announce:
                        announced.setdefault(change.nlri.family(),
                                             {})[change.nlri.index()] = change
                    else:
                        family = change.nlri.family()
                        if family in announced:
                            announced[family].pop(change.nlri.index(), None)