Signed-off-by: ISHIDA Wataru <[email protected]>
---
ryu/services/protocols/bgp/api/rtconf.py | 9 +++
ryu/services/protocols/bgp/bgpspeaker.py | 29 ++++++++++
ryu/services/protocols/bgp/peer.py | 70 +++++++++++++++++++-----
ryu/services/protocols/bgp/rtconf/neighbors.py | 27 ++++++++-
4 files changed, 118 insertions(+), 17 deletions(-)
diff --git a/ryu/services/protocols/bgp/api/rtconf.py
b/ryu/services/protocols/bgp/api/rtconf.py
index 6ddc66e..13d90f0 100644
--- a/ryu/services/protocols/bgp/api/rtconf.py
+++ b/ryu/services/protocols/bgp/api/rtconf.py
@@ -81,6 +81,9 @@ def update_neighbor(neigh_ip_address, changes):
if k == neighbors.OUT_FILTER:
rets.append(_update_outfilter(neigh_ip_address, v))
+ if k == neighbors.IN_FILTER:
+ rets.append(_update_infilter(neigh_ip_address, v))
+
return all(rets)
@@ -91,6 +94,12 @@ def _update_med(neigh_ip_address, value):
return True
+def _update_infilter(neigh_ip_address, value):
+ neigh_conf = _get_neighbor_conf(neigh_ip_address)
+ neigh_conf.in_filter = value
+ return True
+
+
def _update_outfilter(neigh_ip_address, value):
neigh_conf = _get_neighbor_conf(neigh_ip_address)
neigh_conf.out_filter = value
diff --git a/ryu/services/protocols/bgp/bgpspeaker.py
b/ryu/services/protocols/bgp/bgpspeaker.py
index c482fd5..620a857 100644
--- a/ryu/services/protocols/bgp/bgpspeaker.py
+++ b/ryu/services/protocols/bgp/bgpspeaker.py
@@ -52,6 +52,7 @@ from ryu.services.protocols.bgp.rtconf.neighbors import
DEFAULT_CAP_MBGP_VPNV4
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_VPNV6
from ryu.services.protocols.bgp.rtconf.neighbors import PEER_NEXT_HOP
from ryu.services.protocols.bgp.rtconf.neighbors import PASSWORD
+from ryu.services.protocols.bgp.rtconf.neighbors import IN_FILTER
from ryu.services.protocols.bgp.rtconf.neighbors import OUT_FILTER
from ryu.services.protocols.bgp.application import RyuBGPSpeaker
from ryu.lib.packet.bgp import RF_IPv4_UC, RF_IPv6_UC
@@ -59,6 +60,8 @@ from ryu.lib.packet.bgp import RF_IPv4_UC, RF_IPv6_UC
OUT_FILTER_RF_IPv4_UC = RF_IPv4_UC
OUT_FILTER_RF_IPv6_UC = RF_IPv6_UC
+IN_FILTER_RF_IPv4_UC = RF_IPv4_UC
+IN_FILTER_RF_IPv6_UC = RF_IPv6_UC
class EventPrefix(object):
@@ -387,3 +390,29 @@ class BGPSpeaker(object):
param[neighbors.IP_ADDRESS] = address
settings = call(func_name, **param)
return settings[OUT_FILTER]
+
+ def in_filter_set(self, address, prefix_lists,
+ route_family=IN_FILTER_RF_IPv4_UC):
+ assert route_family in (IN_FILTER_RF_IPv4_UC,
+ IN_FILTER_RF_IPv6_UC),\
+ "route family must be IPv4 or IPv6"
+
+ if prefix_lists is None:
+ prefix_lists = []
+
+ func_name = 'neighbor.update'
+ prefix_value = {'prefix_lists': prefix_lists,
+ 'route_family': route_family}
+ filter_param = {neighbors.IN_FILTER: prefix_value}
+
+ param = {}
+ param[neighbors.IP_ADDRESS] = address
+ param[neighbors.CHANGES] = filter_param
+ call(func_name, **param)
+
+ def in_filter_get(self, address):
+ func_name = 'neighbor.get'
+ param = {}
+ param[neighbors.IP_ADDRESS] = address
+ settings = call(func_name, **param)
+ return settings[IN_FILTER]
diff --git a/ryu/services/protocols/bgp/peer.py
b/ryu/services/protocols/bgp/peer.py
index 95cfa6f..5685189 100644
--- a/ryu/services/protocols/bgp/peer.py
+++ b/ryu/services/protocols/bgp/peer.py
@@ -1180,6 +1180,23 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
if withdraw_list:
self._extract_and_handle_bgp4_withdraws(withdraw_list)
+ def _apply_in_filter(self, path):
+ block = False
+ blocked_cause = None
+ prefix_lists = self._neigh_conf.in_filter
+
+ for prefix_list in prefix_lists:
+ policy, is_matched = prefix_list.evaluate(path)
+ if policy == PrefixList.POLICY_PERMIT and is_matched:
+ block = False
+ break
+ elif policy == PrefixList.POLICY_DENY and is_matched:
+ block = True
+ blocked_cause = prefix_list.prefix + ' - DENY'
+ break
+
+ return block, blocked_cause
+
def _extract_and_handle_bgp4_new_paths(self, update_msg):
"""Extracts new paths advertised in the given update message's
*MpReachNlri* attribute.
@@ -1227,9 +1244,15 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
nexthop=next_hop
)
LOG.debug('Extracted paths from Update msg.: %s' % new_path)
- # Update appropriate table with new paths.
- tm = self._core_service.table_manager
- tm.learn_path(new_path)
+
+ block, blocked_cause = self._apply_in_filter(new_path)
+ if not block:
+ # Update appropriate table with new paths.
+ tm = self._core_service.table_manager
+ tm.learn_path(new_path)
+ else:
+ LOG.debug('prefix : %s is blocked by in-bound filter : %s'
+ % (msg_nlri, blocked_cause))
# If update message had any qualifying new paths, do some book-keeping.
if msg_nlri_list:
@@ -1276,9 +1299,15 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
w_nlri,
is_withdraw=True
)
- # Update appropriate table with withdraws.
- tm = self._core_service.table_manager
- tm.learn_path(w_path)
+
+ block, blocked_cause = self._apply_in_filter(w_path)
+ if block:
+ # Update appropriate table with withdraws.
+ tm = self._core_service.table_manager
+ tm.learn_path(w_path)
+ else:
+ LOG.debug('prefix : %s is blocked by in-bound filter : %s'
+ % (msg_nlri, blocked_cause))
def _extract_and_handle_mpbgp_new_paths(self, update_msg):
"""Extracts new paths advertised in the given update message's
@@ -1356,13 +1385,19 @@ class Peer(Source, Sink, NeighborConfListener,
Activity):
nexthop=next_hop
)
LOG.debug('Extracted paths from Update msg.: %s' % new_path)
- if msg_rf == RF_RTC_UC \
- and self._init_rtc_nlri_path is not None:
- self._init_rtc_nlri_path.append(new_path)
+
+ block, blocked_cause = self._apply_in_filter(new_path)
+ if block:
+ if msg_rf == RF_RTC_UC \
+ and self._init_rtc_nlri_path is not None:
+ self._init_rtc_nlri_path.append(new_path)
+ else:
+ # Update appropriate table with new paths.
+ tm = self._core_service.table_manager
+ tm.learn_path(new_path)
else:
- # Update appropriate table with new paths.
- tm = self._core_service.table_manager
- tm.learn_path(new_path)
+ LOG.debug('prefix : %s is blocked by in-bound filter : %s'
+ % (msg_nlri, blocked_cause))
# If update message had any qualifying new paths, do some book-keeping.
if msg_nlri_list:
@@ -1409,9 +1444,14 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
w_nlri,
is_withdraw=True
)
- # Update appropriate table with withdraws.
- tm = self._core_service.table_manager
- tm.learn_path(w_path)
+ block, blocked_cause = self._apply_in_filter(w_path)
+ if block:
+ # Update appropriate table with withdraws.
+ tm = self._core_service.table_manager
+ tm.learn_path(w_path)
+ else:
+ LOG.debug('prefix : %s is blocked by in-bound filter : %s'
+ % (w_nlri, blocked_cause))
def _handle_eor(self, route_family):
"""Currently we only handle EOR for RTC address-family.
diff --git a/ryu/services/protocols/bgp/rtconf/neighbors.py
b/ryu/services/protocols/bgp/rtconf/neighbors.py
index 39b58e3..5b195ad 100644
--- a/ryu/services/protocols/bgp/rtconf/neighbors.py
+++ b/ryu/services/protocols/bgp/rtconf/neighbors.py
@@ -74,6 +74,7 @@ LOCAL_ADDRESS = 'local_address'
LOCAL_PORT = 'local_port'
PEER_NEXT_HOP = 'next_hop'
PASSWORD = 'password'
+IN_FILTER = 'in_filter'
OUT_FILTER = 'out_filter'
# Default value constants.
@@ -87,6 +88,7 @@ DEFAULT_CAP_MBGP_VPNV6 = False
DEFAULT_HOLD_TIME = 40
DEFAULT_ENABLED = True
DEFAULT_CAP_RTC = False
+DEFAULT_IN_FILTER = []
DEFAULT_OUT_FILTER = []
# Default value for *MAX_PREFIXES* setting is set to 0.
@@ -105,7 +107,7 @@ def validate_enabled(enabled):
@validate(name=CHANGES)
def validate_changes(changes):
for k, v in changes.iteritems():
- if k not in (MULTI_EXIT_DISC, ENABLED, OUT_FILTER):
+ if k not in (MULTI_EXIT_DISC, ENABLED, IN_FILTER, OUT_FILTER):
raise ConfigValueError(desc="Unknown field to change: %s" % k)
if k == MULTI_EXIT_DISC:
@@ -202,6 +204,11 @@ def valid_filter(filter_):
return SUPPORTED_FILTER_VALIDATORS[filter_['type']](filter_)
+@validate(name=IN_FILTER)
+def validate_in_filters(filters):
+ return [valid_filter(filter_) for filter_ in filters]
+
+
@validate(name=OUT_FILTER)
def validate_out_filters(filters):
return [valid_filter(filter_) for filter_ in filters]
@@ -226,7 +233,7 @@ class NeighborConf(ConfWithId, ConfWithStats):
ADVERTISE_PEER_AS, SITE_OF_ORIGINS,
LOCAL_ADDRESS, LOCAL_PORT,
PEER_NEXT_HOP, PASSWORD,
- OUT_FILTER])
+ IN_FILTER, OUT_FILTER])
def __init__(self, **kwargs):
super(NeighborConf, self).__init__(**kwargs)
@@ -252,6 +259,8 @@ class NeighborConf(ConfWithId, ConfWithStats):
MAX_PREFIXES, DEFAULT_MAX_PREFIXES, **kwargs)
self._settings[ADVERTISE_PEER_AS] = compute_optional_conf(
ADVERTISE_PEER_AS, DEFAULT_ADVERTISE_PEER_AS, **kwargs)
+ self._settings[IN_FILTER] = compute_optional_conf(
+ IN_FILTER, DEFAULT_IN_FILTER, **kwargs)
self._settings[OUT_FILTER] = compute_optional_conf(
OUT_FILTER, DEFAULT_OUT_FILTER, **kwargs)
@@ -421,6 +430,20 @@ class NeighborConf(ConfWithId, ConfWithStats):
return self._settings[RTC_AS]
@property
+ def in_filter(self):
+ return self._settings[IN_FILTER]
+
+ @in_filter.setter
+ def in_filter(self, value):
+ self._settings[IN_FILTER] = []
+ prefix_lists = value['prefix_lists']
+ for prefix_list in prefix_lists:
+ # copy PrefixList object and put it in the _settings
+ self._settings[IN_FILTER].append(prefix_list.clone())
+
+ LOG.debug('set in-filter : %s' % prefix_lists)
+
+ @property
def out_filter(self):
return self._settings[OUT_FILTER]
--
1.7.10.4
------------------------------------------------------------------------------
Infragistics Professional
Build stunning WinForms apps today!
Reboot your WinForms applications with our WinForms controls.
Build a bridge from your legacy apps to the future.
http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel