Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for parsing the Path Attribute: BGP Prefix-SID (Type 40) in BGP UPDATE Message #167

Merged
merged 5 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ jobs:
strategy:
fail-fast: false
matrix:
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
os: [ ubuntu-20.04, macos-latest, windows-latest ]
python-version: [ "2.7", "3.6", "3.x" ]
python-version: [ "3.6", "3.x" ]
exclude:
- os: windows-latest
python-version: "2.7"
- python-version: "3.x"

steps:
- uses: actions/checkout@v3
Expand Down
14 changes: 0 additions & 14 deletions .travis.yml

This file was deleted.

1 change: 1 addition & 0 deletions yabgp/common/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
BGPTYPE_TUNNEL_ENCAPS_ATTR = 23 # RFC5512
BGPTYPE_LINK_STATE = 29
BGPTYPE_LARGE_COMMUNITY = 32
BGPTYPE_BGP_PREFIX_SID = 40 # RFC8669 & RFC9252
BGPTYPE_ATTRIBUTE_SET = 128

# BGP Tunnel Encapsulation Attribute Tunnel Types
Expand Down
2 changes: 2 additions & 0 deletions yabgp/message/attribute/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class AttributeFlag(int):
PARTIAL = 0x20 # 32 RFC 4271
TRANSITIVE = 0x40 # 64 RFC 4271
OPTIONAL = 0x80 # 128 RFC 4271

# OPTIONAL_TRANSITIVE = 0xc0 # 192 RFC 4271

def __str_(self):
Expand Down Expand Up @@ -110,6 +111,7 @@ class AttributeID(int):
Traffic_Engineering = 0x18 # 24 [RFC5543]
IPv6_Address_Specific_Extended_Community = 0x19 # 25 [RFC5701]
LARGE_COMMUNITY = 0x20 # 32 [8092]
BGP_PREFIX_SID = 0x28 # 40 [RFC8669 & RFC9252]
LINKSTATE = 0x1d
ATTR_SET = 0x80 # 128 [RFC6368]

Expand Down
4 changes: 2 additions & 2 deletions yabgp/message/attribute/linkstate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
from .link.unidirect_avail_bw import UnidirectAvailBw # noqa
from .link.unidirect_bw_util import UnidirectBwUtil # noqa
from .link.extend_admin_group import ExtendedAdminGroup # noqa
from .link.srv6_end_x_sid import SRv6EndXSid # noqa
from .link.srv6_lan_end_x_sid import SRv6LANEndXSid # noqa
from .link.srv6_end_x_sid import SRv6EndXSID # noqa
from .link.srv6_lan_end_x_sid import SRv6LANEndXSID # noqa
from .link.srv6_sid import SRv6SID # noqa
from .prefix.prefix_metric import PrefixMetric # noqa
from .prefix.prefix_sid import PrefixSID # noqa
Expand Down
2 changes: 1 addition & 1 deletion yabgp/message/attribute/linkstate/link/srv6_end_x_sid.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


@LinkState.register()
class SRv6EndXSid(TLV):
class SRv6EndXSID(TLV):
"""
SRv6 End.X SID
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

@LinkState.register(_type=1107) # IS-IS
@LinkState.register(_type=1108) # OSPFv3
class SRv6LANEndXSid(TLV):
class SRv6LANEndXSID(TLV):
"""
SRv6 LAN End.X SID

Expand Down
19 changes: 19 additions & 0 deletions yabgp/message/attribute/sr/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2024 Cisco Systems, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from .bgpprefixsid import BGPPrefixSID # noqa
from .srv6.l3service import SRv6L3Service # noqa
from .srv6.sidinformation import SRv6SIDInformation # noqa
from .srv6.sidstructure import SRv6SIDStructure # noqa
83 changes: 83 additions & 0 deletions yabgp/message/attribute/sr/bgpprefixsid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright 2024 Cisco Systems, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import struct

import binascii

from yabgp.message.attribute import Attribute, AttributeFlag, AttributeID


class BGPPrefixSID(Attribute):
"""
BGP Prefix SID

Original: https://datatracker.ietf.org/doc/html/rfc8669#section-3
Extend: https://datatracker.ietf.org/doc/html/rfc9252#section-2
"""

ID = AttributeID.BGP_PREFIX_SID
FLAG = AttributeFlag.OPTIONAL + AttributeFlag.TRANSITIVE

registered_tlvs = dict()

def __init__(self, value, hex_value=None):
self.value = value
self.hex_value = hex_value

@classmethod
def register(cls, _type=None):
"""

:param _type:
:return:
"""

def decorator(klass):
"""

:param klass:
:return:
"""
_id = klass.TYPE if _type is None else _type
if _id in cls.registered_tlvs:
raise RuntimeError('Duplicated attribute type')
cls.registered_tlvs[_id] = klass
return klass

return decorator

@classmethod
def unpack(cls, data):
"""

:param data:
:return:
"""
tlvs = []
while data:
type_code = data[0] # Note: Type = 1 octet
length = struct.unpack('!H', data[1:3])[0] # Note: Length = 2 octet
value = data[3: 3 + length]

if type_code in cls.registered_tlvs:
tlvs.append(cls.registered_tlvs[type_code].unpack(value))
else:
tlvs.append({
'type': type_code,
'value': str(binascii.b2a_hex(value))
})
data = data[3 + length:]
return tlvs
8 changes: 8 additions & 0 deletions yabgp/message/attribute/sr/srv6/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# +---------------+---------------------------------+----------+-----------------+
# | TLV Code | Description | Length | Reference |
# | Point | | | |
# +---------------+---------------------------------+----------+-----------------+
# | 5 | SRv6 L3 Service TLV | variable | Section 2 |
# | 1 | SRv6 SID Information Sub-TLV | variable | Section 3.1 |
# | 1 | SRv6 SID Structure Sub-Sub-TLV | 6 | Section 3.2.1 |
# +---------------+---------------------------------+----------+-----------------+
96 changes: 96 additions & 0 deletions yabgp/message/attribute/sr/srv6/l3service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Copyright 2024 Cisco Systems, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import struct

import binascii

from yabgp.tlv import TLV
from ..bgpprefixsid import BGPPrefixSID


# 2. SRv6 Services TLVs
#
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | TLV Type | TLV Length | RESERVED |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | SRv6 Service Sub-TLVs //
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#
# Figure 1: SRv6 Service TLVs


@BGPPrefixSID.register()
class SRv6L3Service(TLV):
"""
SRv6 L3 Service
"""
TYPE = 5 # https://datatracker.ietf.org/doc/html/rfc9252.html#section-2
TYPE_STR = 'srv6_l3_service'

registered_tlvs = dict()

@classmethod
def register(cls, _type=None):
"""

:param _type:
:return:
"""

def decorator(klass):
"""

:param klass:
:return:
"""
_id = klass.TYPE if _type is None else _type
if _id in cls.registered_tlvs:
raise RuntimeError('Duplicated SRv6 Service Sub-TLV type')
cls.registered_tlvs[_id] = klass
return klass

return decorator

@classmethod
def unpack(cls, data):
"""

:param data:
:return:
"""
tlvs = []

# reserved = data[0:1] # Note: First byte is reserved
data = data[1:]
while data:
srv6_service_sub_tlv_type_code = data[0] # Note: Type = 1 octet
srv6_service_sub_tlv_length = struct.unpack('!H', data[1:3])[0] # Note: Length = 2 octet
value = data[3: 3 + srv6_service_sub_tlv_length]

if srv6_service_sub_tlv_type_code in cls.registered_tlvs:
tlvs.append(cls.registered_tlvs[srv6_service_sub_tlv_type_code].unpack(value))
else:
tlvs.append({
'type': srv6_service_sub_tlv_type_code,
'value': str(binascii.b2a_hex(value))
})
data = data[3 + srv6_service_sub_tlv_length:]
value = {
'srv6_service_sub_tlvs': tlvs
}
return {cls.TYPE_STR: value}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def dict(cls)ordef dict(self)

Loading
Loading