Skip to content

Commit

Permalink
Merge pull request #1206 from mxyns/main
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-mangin committed Apr 15, 2024
2 parents 826c450 + 38fd944 commit 7efbbf5
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/exabgp/bgp/neighbor.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Capability(dict):
'description': '',
'router-id': None,
'local-address': None,
'source-interface': None,
'peer-address': None,
'local-as': None,
'peer-as': None,
Expand Down Expand Up @@ -397,6 +398,7 @@ def string(self, with_changes=True):
'\thost-name %s;\n'
'\tdomain-name %s;\n'
'\tlocal-address %s;\n'
'\tsource-interface %s;\n'
'\tlocal-as %s;\n'
'\tpeer-as %s;\n'
'\thold-time %s;\n'
Expand All @@ -421,6 +423,7 @@ def string(self, with_changes=True):
self['host-name'],
self['domain-name'],
self['local-address'] if not self.auto_discovery else 'auto',
self['source-interface'],
self['local-as'],
self['peer-as'],
self['hold-time'],
Expand Down
3 changes: 3 additions & 0 deletions src/exabgp/configuration/neighbor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from exabgp.configuration.neighbor.parser import hold_time
from exabgp.configuration.neighbor.parser import router_id
from exabgp.configuration.neighbor.parser import local_address
from exabgp.configuration.neighbor.parser import source_interface
from exabgp.configuration.neighbor.parser import hostname
from exabgp.configuration.neighbor.parser import domainname
from exabgp.configuration.neighbor.parser import description
Expand All @@ -63,6 +64,7 @@ class ParseNeighbor(Section):
'hold-time': hold_time,
'rate-limit': rate_limit,
'local-address': local_address,
'source-interface': source_interface,
'peer-address': peer_ip,
'local-as': auto_asn,
'peer-as': auto_asn,
Expand Down Expand Up @@ -90,6 +92,7 @@ class ParseNeighbor(Section):
'hold-time': 'set-command',
'rate-limit': 'set-command',
'local-address': 'set-command',
'source-interface': 'set-command',
'peer-address': 'set-command',
'local-as': 'set-command',
'peer-as': 'set-command',
Expand Down
8 changes: 7 additions & 1 deletion src/exabgp/configuration/neighbor/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ def local_address(tokeniser):
except (IndexError, ValueError, socket.error):
raise ValueError('"%s" is an invalid IP address' % value)

def source_interface(tokeniser):
try:
return string(tokeniser)
except Exception:
raise ValueError('bad source interface')


def router_id(tokeniser):
value = tokeniser()
Expand Down Expand Up @@ -175,4 +181,4 @@ def rate_limit(tokeniser):
raise ValueError('"%s" is an invalid rate-limit' % value)
if rate <= 0:
raise ValueError('rate must be zero or at 1 (per second)')
return rate
return rate
5 changes: 3 additions & 2 deletions src/exabgp/reactor/network/outgoing.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@
class Outgoing(Connection):
direction = 'outgoing'

def __init__(self, afi, peer, local, port=179, md5='', md5_base64=False, ttl=None):
def __init__(self, afi, peer, local, port=179, md5='', md5_base64=False, ttl=None, itf=None):
Connection.__init__(self, afi, peer, local)

self.ttl = ttl
self.afi = afi
self.md5 = md5
self.md5_base64 = md5_base64
self.port = port
self.interface = itf

def _setup(self):
try:
self.io = create(self.afi)
self.io = create(self.afi, self.interface)
MD5(self.io, self.peer, self.port, self.md5, self.md5_base64)
if self.afi == AFI.ipv4:
TTL(self.io, self.peer, self.ttl)
Expand Down
11 changes: 10 additions & 1 deletion src/exabgp/reactor/network/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from exabgp.logger import log


def create(afi):
def create(afi, interface=None):
try:
if afi == AFI.ipv4:
io = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
Expand All @@ -46,6 +46,15 @@ def create(afi):
io.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) # pylint: disable=E1101
except (socket.error, AttributeError):
pass

if interface is not None:
try:
if not hasattr(socket,'SO_BINDTODEVICE') :
socket.SO_BINDTODEVICE = 25

io.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, str(interface + '\0').encode("utf-8"))
except socket.error:
raise NotConnected(f'Could not bind to device {interface}')
except socket.error:
raise NotConnected('Could not create socket')
return io
Expand Down
3 changes: 2 additions & 1 deletion src/exabgp/reactor/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def connect(self):
md5 = self.neighbor['md5-password']
md5_base64 = self.neighbor['md5-base64']
ttl_out = self.neighbor['outgoing-ttl']
self.connection = Outgoing(afi, peer, local, self.port, md5, md5_base64, ttl_out)
itf = self.neighbor['source-interface']
self.connection = Outgoing(afi, peer, local, self.port, md5, md5_base64, ttl_out, itf)

for connected in self.connection.establish():
yield False
Expand Down

0 comments on commit 7efbbf5

Please sign in to comment.