Skip to content

Commit

Permalink
Merge pull request #1223 from ton31337/feature/bgp_software_version_c…
Browse files Browse the repository at this point in the history
…apability

Implement software version capability for BGP (needs fixing)
  • Loading branch information
thomas-mangin authored Jul 15, 2024
2 parents ec2f2e7 + c2a2ea8 commit 29adbfb
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 4 deletions.
15 changes: 15 additions & 0 deletions etc/exabgp/conf-cap-software-version.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
neighbor 127.0.0.1 {
router-id 10.0.0.2;
local-address 127.0.0.1;
local-as 65533;
peer-as 65533;
hold-time 180;

capability {
software-version enable;
}

family {
ipv4 unicast;
}
}
1 change: 1 addition & 0 deletions qa/encoding/conf-cap-software-version.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
conf-cap-software-version.conf
2 changes: 2 additions & 0 deletions qa/encoding/conf-cap-software-version.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
option:open:inspect-open-message
1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0051:01:04FFFD00B40A000002340206010400010001020641040000FFFD02224B201F4578614247502F6D61696E2D346634323232663265642D3230323430373135
6 changes: 4 additions & 2 deletions sbin/exabgp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ if [ $? -eq 0 ]; then
GIT_TAG=`git status | egrep 'detached at 3|4' | wc -l`
if [ $GIT_TAG -eq 0 ]; then
GIT_BRANCH=`git branch | grep "*" | awk '{ print $2}'`
GIT_COMMIT=`git log -1 | head -1 | awk '{ print $2 }'`
export EXABGP_VERSION="${GIT_BRANCH}-${GIT_COMMIT}"
GIT_COMMIT=`git rev-parse --short=10 HEAD`
export EXABGP_VERSION="main-${GIT_COMMIT}-$(date +%Y%m%d)"
fi
else
export EXABGP_VERSION="main-unknown-$(date +%Y%m%d)"
fi


Expand Down
8 changes: 8 additions & 0 deletions src/exabgp/bgp/message/open/capability/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from exabgp.bgp.message.open.capability.refresh import EnhancedRouteRefresh
from exabgp.bgp.message.open.capability.extended import ExtendedMessage
from exabgp.bgp.message.open.capability.hostname import HostName
from exabgp.bgp.message.open.capability.software_version import SoftwareVersion

from exabgp.bgp.message.notification import Notify

Expand Down Expand Up @@ -142,6 +143,12 @@ def _extended_message(self, neighbor):
def _hostname(self, neighbor):
self[Capability.CODE.HOSTNAME] = HostName(neighbor['host-name'], neighbor['domain-name'])

def _software_version(self, neighbor):
if not neighbor['capability']['software-version']:
return

self[Capability.CODE.SOFTRWARE_VERSION] = SoftwareVersion()

def _operational(self, neighbor):
if not neighbor['capability']['operational']:
return
Expand All @@ -163,6 +170,7 @@ def new(self, neighbor, restarted):
self._operational(neighbor)
self._extended_message(neighbor)
self._hostname(neighbor) # https://datatracker.ietf.org/doc/html/draft-walton-bgp-hostname-capability-02
self._software_version(neighbor) # https://datatracker.ietf.org/doc/html/draft-abraitis-bgp-version-capability
self._session(neighbor) # MUST be the last key added, really !?! dict is not ordered !
return self

Expand Down
3 changes: 3 additions & 0 deletions src/exabgp/bgp/message/open/capability/capability.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class _CapabilityCode(int):
MULTISESSION_CISCO = 0x83 # What Cisco really use for Multisession (yes this is a reserved range in prod !)

HOSTNAME = 0x49 # https://datatracker.ietf.org/doc/html/draft-walton-bgp-hostname-capability-02
SOFTWARE_VERSION = 0x4B # https://datatracker.ietf.org/doc/html/draft-abraitis-bgp-version-capability
OPERATIONAL = 0xB9 # ExaBGP only ...

# Internal
Expand All @@ -61,6 +62,7 @@ class _CapabilityCode(int):
MULTISESSION_CISCO: 'cisco-multi-sesion',
AIGP: 'aigp',
HOSTNAME: 'hostname',
SOFTWARE_VERSION: 'software-version',
}

def __new__(cls, value):
Expand Down Expand Up @@ -105,6 +107,7 @@ class CODE(int):
ROUTE_REFRESH_CISCO = _CapabilityCode(_CapabilityCode.ROUTE_REFRESH_CISCO)
MULTISESSION_CISCO = _CapabilityCode(_CapabilityCode.MULTISESSION_CISCO)
HOSTNAME = _CapabilityCode(_CapabilityCode.HOSTNAME)
SOFTRWARE_VERSION = _CapabilityCode(_CapabilityCode.SOFTWARE_VERSION)
OPERATIONAL = _CapabilityCode(_CapabilityCode.OPERATIONAL)
AIGP = _CapabilityCode(_CapabilityCode.AIGP)
# fmt: on
Expand Down
40 changes: 40 additions & 0 deletions src/exabgp/bgp/message/open/capability/software_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# encoding: utf-8
"""
software_version.py
Copyright (c) 2024 Donatas Abraitis. All rights reserved.
License: 3-clause BSD. (See the COPYRIGHT file)
"""

# https://datatracker.ietf.org/doc/html/draft-abraitis-bgp-version-capability


from exabgp.bgp.message.open.capability.capability import Capability
from exabgp.version import version


@Capability.register()
class SoftwareVersion(Capability):
ID = Capability.CODE.SOFTRWARE_VERSION
SOFTWARE_VERSION_MAX_LEN = 64

def __init__(self):
self.software_version = f"ExaBGP/{version}"

def __str__(self):
return f'SoftwareVersion({self.software_version})'

def json(self):
return f'{ "software-version": "{self.software_version}" }'

def extract(self):
software_version = self.software_version.encode('utf-8')
if len(software_version) > self.SOFTWARE_VERSION_MAX_LEN:
software_version = software_version[: self.SOFTWARE_VERSION_MAX_LEN]
return [bytes([len(software_version)]) + software_version]

@staticmethod
def unpack_capability(instance, data, capability=None): # pylint: disable=W0613
l1 = data[0]
instance.software_version = data[1 : l1 + 1].decode('utf-8')
return instance
5 changes: 4 additions & 1 deletion src/exabgp/bgp/neighbor.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Capability(dict):
'route-refresh': 0,
'nexthop': None,
'aigp': None,
'software-version': None,
}

defaults = {
Expand Down Expand Up @@ -406,7 +407,7 @@ def string(self, with_changes=True):
'\tmanual-eor %s;\n'
'%s%s%s%s%s%s%s%s%s%s%s\n'
'\tcapability {\n'
'%s%s%s%s%s%s%s%s%s\t}\n'
'%s%s%s%s%s%s%s%s%s%s\t}\n'
'\tfamily {%s\n'
'\t}\n'
'\tnexthop {%s\n'
Expand Down Expand Up @@ -446,6 +447,8 @@ def string(self, with_changes=True):
'\t\troute-refresh %s;\n' % ('enable' if self['capability']['route-refresh'] else 'disable'),
'\t\tgraceful-restart %s;\n'
% (self['capability']['graceful-restart'] if self['capability']['graceful-restart'] else 'disable'),
'\t\tsoftware-version %s;\n'
% ('enable' if self['capability']['software-version'] else 'disable'),
'\t\tnexthop %s;\n' % ('enable' if self['capability']['nexthop'] else 'disable'),
'\t\tadd-path %s;\n'
% (AddPath.string[self['capability']['add-path']] if self['capability']['add-path'] else 'disable'),
Expand Down
4 changes: 4 additions & 0 deletions src/exabgp/configuration/capability.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class ParseCapability(Section):
' operational enable|disable;\n'
' refresh enable|disable;\n'
' extended-message enable|disable;\n'
' software-version enable|disable;\n'
'}\n'
)

Expand All @@ -84,6 +85,7 @@ class ParseCapability(Section):
'route-refresh': boolean,
'aigp': boolean,
'extended-message': boolean,
'software-version': boolean,
}

action = {
Expand All @@ -96,6 +98,7 @@ class ParseCapability(Section):
'route-refresh': 'set-command',
'aigp': 'set-command',
'extended-message': 'set-command',
'software-version': 'set-command',
}

default = {
Expand All @@ -107,6 +110,7 @@ class ParseCapability(Section):
'route-refresh': True,
'aigp': True,
'extended-message': True,
'software-version': False,
}

name = 'capability'
Expand Down
1 change: 1 addition & 0 deletions src/exabgp/configuration/neighbor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from exabgp.configuration.neighbor.parser import description
from exabgp.configuration.neighbor.parser import inherit
from exabgp.configuration.neighbor.parser import rate_limit
from exabgp.version import version

from exabgp.environment import getenv

Expand Down
3 changes: 2 additions & 1 deletion tests/decode_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from exabgp.bgp.message.update.nlri import NLRI

from exabgp.bgp.message.direction import Direction

from exabgp.logger import log
from exabgp.environment import getenv

Expand Down Expand Up @@ -328,6 +328,7 @@ def __init__(self):
'aigp': None,
'operational': None,
'extended-message': True,
'software-version': False,
},
})

Expand Down

0 comments on commit 29adbfb

Please sign in to comment.