Skip to content

Commit

Permalink
Add support for revised RFC8227 withdraw labels
Browse files Browse the repository at this point in the history
This commit fixes a parsing error when a BGP update contains a "withdraw label"
equal to 0x000000 instead of 0x8000000 as stated in RFC 3107. This commits
treats both labels as "withdraw label"

Signed-off-by: Benjamin Villain <villainb@amazon.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
  • Loading branch information
Benjamin Villain via Ryu-devel authored and fujita committed Sep 25, 2019
1 parent 4e0fc9e commit 0866cb7
Showing 1 changed file with 13 additions and 4 deletions.
17 changes: 13 additions & 4 deletions ryu/lib/packet/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,16 @@ class _LabelledAddrPrefix(_AddrPrefix):
# Routes field should be set to 0x800000. (Of course, terminating the
# BGP session also withdraws all the previously advertised routes.)
#
_WITHDRAW_LABEL = 0x800000
# RFC8227
# 2.4 How to Explicitly Withdraw the Binding of a Label to a Prefix
# [RFC3107] also made it possible to withdraw a binding without specifying
# the label explicitly, by setting the Compatibility field to 0x800000.
# However, some implementations set it to 0x000000. In order to ensure
# backwards compatibility, it is RECOMMENDED by this document that the
# Compatibility field be set to 0x800000, but it is REQUIRED that it be
# ignored upon reception.
#
_WITHDRAW_LABELS = [0x800000, 0x000000]

def __init__(self, length, addr, labels=None, **kwargs):
labels = labels if labels else []
Expand Down Expand Up @@ -823,7 +832,7 @@ def _to_bin(cls, addr):
labels = addr[0]
rest = addr[1:]
labels = [x << 4 for x in labels]
if labels and labels[-1] != cls._WITHDRAW_LABEL:
if labels and labels[-1] not in cls._WITHDRAW_LABELS:
labels[-1] |= 1 # bottom of stack
bin_labels = list(cls._label_to_bin(l) for l in labels)
return bytes(reduce(lambda x, y: x + y, bin_labels,
Expand All @@ -837,7 +846,7 @@ def _has_no_label(cls, bin_):
while True:
(label, bin_) = cls._label_from_bin(bin_)
labels.append(label)
if label & 1 or label == cls._WITHDRAW_LABEL:
if label & 1 or label in cls._WITHDRAW_LABELS:
break
assert length > struct.calcsize(cls._LABEL_PACK_STR) * len(labels)
except struct.error:
Expand All @@ -857,7 +866,7 @@ def _from_bin(cls, addr):
while True:
(label, rest) = cls._label_from_bin(rest)
labels.append(label >> 4)
if label & 1 or label == cls._WITHDRAW_LABEL:
if label & 1 or label in cls._WITHDRAW_LABELS:
break
return (labels,) + cls._prefix_from_bin(rest)

Expand Down

0 comments on commit 0866cb7

Please sign in to comment.