Skip to content

Commit

Permalink
fixes and remove support for announce/withdraw
Browse files Browse the repository at this point in the history
remove the feature from the code as it is not used anymore and the
implenentation was not nice.
  • Loading branch information
thomas-mangin committed Sep 25, 2024
1 parent a45604c commit 42553f1
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 92 deletions.
2 changes: 1 addition & 1 deletion qa/bin/functional-3.6
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class CI(dict):
def make(cls):
for filename in Path.ALL_CI:
name, extension = os.path.splitext(filename.split('/')[-1])
if name in ['api-reload', 'api-notification', 'conf-ebgp', 'conf-ipself6', 'conf-cap-software-version', 'conf-hostname']:
if name in ['api-reload', 'api-notification', 'conf-ebgp', 'conf-ipself6', 'conf-cap-software-version', 'conf-hostname', 'api-rr']:
continue
nick = Identifier.get(name)
with open(filename, 'r') as reader:
Expand Down
161 changes: 70 additions & 91 deletions qa/sbin/bgp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ def print_payload(prefix, header, body):


def print_rule(prefix, rule):
flushed(f'{prefix:12}{rule[:32]}:{rule[32:36]}:{rule[36:38]}:{rule[38:]}')
print_tab(prefix,f'{rule[:32]}:{rule[32:36]}:{rule[36:38]}:{rule[38:]}')


def print_tab(prefix, rule):
flushed(f'{prefix:12}{rule}')


def dump(value):
Expand Down Expand Up @@ -208,7 +212,7 @@ class Message:
]
* 16
+ [0x0, 0x17, 0x02]
+ +[0x00, 0x00, 0x00, 0x00]
+ [0x00, 0x00, 0x00, 0x00]
)

@staticmethod
Expand Down Expand Up @@ -274,13 +278,27 @@ class Message:
def is_keepalive(self):
return self.kind() == 4

def is_route_refresh(self):
return self.kind() == 5

def is_eor(self):
if not self.is_update():
return False
return len(self.body) in [4, 11]

def name(self, header):
return self._name.get(self.kind(), 'SOME WEIRD RFC PACKET')

def notification(self):
yield bytestream(self.body)
# yield 'notification:%d,%d' % (self.body[0], self.body[1])

def stream(self):
return bytestream(self.header + self.body)

def packet(self):
return bytearray(self.header + self.body)

def routes(self):
body_len = len(self.body)

Expand Down Expand Up @@ -315,27 +333,6 @@ class Message:
r[index], announced = announced[0], announced[1:]
yield 'announce:%s' % '.'.join(str(_) for _ in r) + '/' + str(cdr)

def parser(self, raw):
if raw:
if self.body:
yield bytestream(self.header + self.body)
return

if self.is_update():
for _ in self.routes():
yield _
return

if self.is_notification():
for _ in self.notification():
yield _
return

if self.is_keepalive():
yield "keepalive"
return
flushed(f'kind is not known {self.kind()}, ignoring')

@staticmethod
def _add_capa66(adding, open):
if not adding:
Expand Down Expand Up @@ -394,6 +391,8 @@ class Message:


class Checker(object):
updates_seen = []

def __init__(self, expected):
self.raw = False
self.messages = []
Expand Down Expand Up @@ -503,62 +502,62 @@ class Checker(object):
self._update_messages_if_required()
return True

def perform_actions_if_required(self, writer):
def _send_rr_if_required(self, writer, msg):
if msg.is_route_refresh():
for header, body in self.updates_seen:
print_payload('rr sent', header, body)
writer.write(Message(header,body).packet())
writer.write(Message.keepalive())

def perform_actions_if_required(self, writer, msg):
self._update_messages_if_required()
self._send_signal_if_requested()
self._update_messages_if_required()
self._send_notification_if_requested(writer)
self._send_rr_if_required(writer, msg)

def _update_messages_if_required(self):
if not self.messages and self.sequences:
self.messages = self.sequences.pop(0)

def is_eor(self, message):
if message == bytestream(Message.eor()):
return True
if message.startswith('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF001E0200000007900F0003'):
# payload with the AFI/SAFI
def expected(self, writer, msg):
if msg.is_keepalive():
return True
return False

def expected(self, received, writer):
if not self.sequences:
if not self.messages:
if self.is_eor(received):
return True
flushed('received extra message')
# FIXME: change API to not have to convert
print_payload('additional', msg_bytes(received[: 19 * 2]), msg_bytes(received[19 * 2 :]))
return False
if not self.sequences and not self.messages:
if msg.is_eor():
return True
flushed('received extra message')
print_payload('additional', msg.header, msg.body)
return False

check = self.messages[0]
stream = msg.stream()

for check in self.messages:
if self.raw:
if not check.startswith('F' * 32) and ':' not in check:
received = received[32:]
received = stream
if not check.startswith('F' * 32) and ':' not in check:
received = received[32:]

if check == received:
self.messages.remove(check)
self.perform_actions_if_required(writer)
if msg.is_update() and not msg.is_eor():
self.updates_seen.append((msg.header,msg.body))

self.perform_actions_if_required(writer, msg)
return True

nb_options = len(self.messages)
flushed('')
flushed('unexpected message:')
if self.raw:
print_payload('received', msg_bytes(received[: 19 * 2]), msg_bytes(received[19 * 2 :]))
else:
print_prefixed('received', received)
print_payload('received', msg.header, msg.body)

flushed(f'\ncounting {nb_options} valid option(s):')
idx = 0
for message in self.messages:
idx += 1
# FIXME: change API to not have to convert
if self.raw or '\xff' in message:
msg = msg_bytes(message)
print_payload(f'option {idx:02}', msg[:19], msg[19:])
else:
print_prefixed(f'option {idx:02}', message)
msg = msg_bytes(message)
print_payload(f'option {idx:02}', msg[:19], msg[19:])
flushed('')
self.rules()
return False
Expand Down Expand Up @@ -629,6 +628,7 @@ class BGPProtocol(asyncio.Protocol):
sys.exit(1)
self.writer.close()


def handle_open(self, msg):
option_asn = self.service.options['asn']
option_capa66 = self.service.options['send-unknown-capability']
Expand All @@ -641,16 +641,17 @@ class BGPProtocol(asyncio.Protocol):
self.writer.write(Message.keepalive())

if option_open:
for announcement in msg.parser(raw=self.service.checker.raw):
if not self.service.checker.expected(announcement, self.writer):
self.service.exit(1)
return FSM.STOP
if not self.service.checker.expected(self.writer, msg):
self.service.exit(1)
return FSM.STOP

if self.service.checker.completed():
self.service.exit(0)
return FSM.STOP

if self.service.checker.completed():
self.service.exit(0)
return FSM.STOP
return FSM.MSG

self.service.checker.perform_actions_if_required(self.writer)
self.service.checker.perform_actions_if_required(self.writer, msg)

if option_default:
flushed('sending default-route\n')
Expand All @@ -672,33 +673,20 @@ class BGPProtocol(asyncio.Protocol):
self.writer.write(header + body)
return FSM.MSG

self.writer.write(Message.keepalive())

# FIXME: raw is probably not where it should
for announcement in msg.parser(raw=self.service.checker.raw):
if announcement == 'keepalive': # skip keepalive
indent(f'skipping {announcement}')
continue
# saving update saved to send them later on rr test

if announcement.startswith('eor:'): # skip EOR
indent(f'skipping {announcement}')
continue
self.writer.write(Message.keepalive())

if announcement.startswith('mp:'): # skip unparsed MP
indent(f'skipping multiprotocol : {dump(body)}')
continue
if not self.service.checker.expected(self.writer, msg):
self.service.exit(1)
return FSM.STOP

if not self.service.checker.expected(announcement, self.writer):
self.service.exit(1)
return FSM.STOP

if self.service.checker.completed():
self.service.exit(0)
return FSM.STOP
if self.service.checker.completed():
self.service.exit(0)
return FSM.STOP

return FSM.MSG


def parse_cmdline():
port = os.environ.get('exabgp.tcp.port', os.environ.get('exabgp_tcp_port', '179'))

Expand All @@ -723,15 +711,6 @@ def parse_cmdline():
and (cmdarg.asn < 0 or cmdarg.asn > 65535)
):
parser.print_help()
flushed('\n')
flushed('a list of expected route announcement/withdrawl in the format:')
flushed(
' <number>:announce:<ipv4-route> <number>:withdraw:<ipv4-route> <number>:raw:<exabgp hex dump : separated>'
)
flushed(' (routes defined under the same <number> are not ordered)')
flushed('\n')
flushed('for example:')
flushed(f' {sys.argv[0]} 1:announce:10.0.0.0/8 1:announce:192.0.2.0/24 2:withdraw:10.0.0.0/8')
sys.exit(1)

# fmt: off
Expand Down

0 comments on commit 42553f1

Please sign in to comment.