bgp: support IPv6 peering

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
FUJITA Tomonori 2014-06-17 17:59:19 +09:00
parent dabcfaa856
commit 3c3a29b535
4 changed files with 36 additions and 13 deletions

View File

@ -21,6 +21,7 @@ import socket
import time
import traceback
import weakref
import netaddr
from ryu.lib import hub
from ryu.lib.hub import Timeout
@ -318,16 +319,24 @@ class Activity(object):
For each connection `server_factory` starts a new protocol.
"""
server = hub.listen(loc_addr)
if ':' in loc_addr[0]:
server = hub.listen(loc_addr, family=socket.AF_INET6)
else:
server = hub.listen(loc_addr)
server_name = self.name + '_server@' + str(loc_addr)
self._asso_socket_map[server_name] = server
# We now wait for connection requests from client.
while True:
sock, client_address = server.accept()
client_address, port = client_address[:2]
LOG.debug('Connect request received from client for port'
' %s:%s' % client_address)
client_name = self.name + '_client@' + str(client_address)
' %s:%s' % (client_address, port))
if 'ffff:' in client_address:
client_address = str(netaddr.IPAddress(client_address).ipv4())
client_name = self.name + '_client@' + client_address
self._asso_socket_map[client_name] = sock
self._spawn(client_name, conn_handle, sock)
@ -341,8 +350,12 @@ class Activity(object):
"""
LOG.debug('Connect TCP called for %s:%s' % (peer_addr[0],
peer_addr[1]))
if netaddr.valid_ipv4(peer_addr[0]):
family = socket.AF_INET
else:
family = socket.AF_INET6
with Timeout(time_out, socket.error):
sock = hub.connect(peer_addr, bind=bind_address)
sock = hub.connect(peer_addr, family=family, bind=bind_address)
if sock:
# Connection name for pro-active connection is made up
# of local end address + remote end address

View File

@ -45,7 +45,7 @@ LOG = logging.getLogger('bgpspeaker.core')
# Interface IP address on which to run bgp server. Core service listens on all
# interfaces of the host on port 179 - standard bgp port.
CORE_IP = '0.0.0.0'
CORE_IP = '::'
# Required dictates that Origin attribute be incomplete
EXPECTED_ORIGIN = BGP_ATTR_ORIGIN_INCOMPLETE
@ -380,7 +380,7 @@ class CoreService(Factory, Activity):
def build_protocol(self, socket):
assert socket
# Check if its a reactive connection or pro-active connection
_, remote_port = socket.getpeername()
_, remote_port = socket.getpeername()[:2]
is_reactive_conn = True
if remote_port == STD_BGP_SERVER_PORT_NUM:
is_reactive_conn = False
@ -399,7 +399,9 @@ class CoreService(Factory, Activity):
protocol.
"""
assert socket
peer_addr, peer_port = socket.getpeername()
peer_addr, peer_port = socket.getpeername()[:2]
if 'ffff:' in peer_addr:
peer_addr = str(netaddr.IPAddress(peer_addr).ipv4())
peer = self._peer_manager.get_by_addr(peer_addr)
bgp_proto = self.build_protocol(socket)
@ -424,7 +426,7 @@ class CoreService(Factory, Activity):
subcode = BGP_ERROR_SUB_CONNECTION_COLLISION_RESOLUTION
bgp_proto.send_notification(code, subcode)
else:
bind_ip, bind_port = socket.getsockname()
bind_ip, bind_port = socket.getsockname()[0:2]
peer._host_bind_ip = bind_ip
peer._host_bind_port = bind_port
self._spawn_activity(bgp_proto, peer)

View File

@ -1,4 +1,5 @@
import logging
import netaddr
from ryu.services.protocols.bgp.base import SUPPORTED_GLOBAL_RF
from ryu.services.protocols.bgp.model import OutgoingRoute
@ -53,7 +54,7 @@ class PeerManager(object):
self._core_service.on_peer_removed(peer)
def get_by_addr(self, addr):
return self._peers.get(addr)
return self._peers.get(str(netaddr.IPAddress(addr)))
def on_peer_down(self, peer):
"""Peer down handler.

View File

@ -18,6 +18,7 @@
"""
from abc import abstractmethod
import logging
import netaddr
from ryu.lib.packet.bgp import RF_IPv4_UC
from ryu.lib.packet.bgp import RF_IPv6_UC
@ -107,20 +108,26 @@ def validate_changes(changes):
return changes
def valid_ip_address(addr):
if not netaddr.valid_ipv4(addr) and not netaddr.valid_ipv6(addr):
return False
return True
@validate(name=IP_ADDRESS)
def validate_ip_address(ip_address):
if not is_valid_ipv4(ip_address):
if not valid_ip_address(ip_address):
raise ConfigValueError(desc='Invalid neighbor ip_address: %s' %
ip_address)
return ip_address
return str(netaddr.IPAddress(ip_address))
@validate(name=LOCAL_ADDRESS)
def validate_local_address(ip_address):
if not is_valid_ipv4(ip_address):
if not valid_ip_address(ip_address):
raise ConfigValueError(desc='Invalid local ip_address: %s' %
ip_address)
return ip_address
return str(netaddr.IPAddress(ip_address))
@validate(name=LOCAL_PORT)