diff options
author | Satoshi Kobayashi <satoshi-k@stratosphere.co.jp> | 2013-10-30 10:53:53 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2013-11-01 10:28:59 +0900 |
commit | 6e5c24219c011da658110448dfaea52d00149262 (patch) | |
tree | f8492d94b29d640f449201125c870de354418924 | |
parent | 9a957e200801b46bcf1307695d6c66fc5f0f0d4e (diff) |
Decoration Based PacketIn Filter
It is noisy when packets goes into a handler of EventOFPPacketIn indiscriminately. Then, we introduce API which filters a packet. API is decorator and a filtering algorithem is pluggable.
Signed-off-by: Satoshi Kobayashi <satoshi-k@stratosphere.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/lib/ofp_pktinfilter.py | 57 | ||||
-rw-r--r-- | ryu/tests/unit/lib/test_ofp_pktinfilter.py | 100 |
2 files changed, 157 insertions, 0 deletions
diff --git a/ryu/lib/ofp_pktinfilter.py b/ryu/lib/ofp_pktinfilter.py new file mode 100644 index 00000000..c3bd9797 --- /dev/null +++ b/ryu/lib/ofp_pktinfilter.py @@ -0,0 +1,57 @@ +# Copyright (C) 2013 Stratosphere Inc. +# +# 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. +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import logging +from abc import ABCMeta, abstractmethod + +from ryu.lib.packet import packet + +LOG = logging.getLogger(__name__) + + +def packet_in_filter(cls, args=None): + def _packet_in_filter(packet_in_handler): + def __packet_in_filter(self, ev): + pkt = packet.Packet(ev.msg.data) + if not packet_in_handler.pkt_in_filter.filter(pkt): + LOG.debug('The packet is discarded by %s: %s' % (cls, pkt)) + return + return packet_in_handler(self, ev) + pkt_in_filter = cls(args) + packet_in_handler.pkt_in_filter = pkt_in_filter + return __packet_in_filter + return _packet_in_filter + + +class PacketInFilterBase(object): + __metaclass__ = ABCMeta + + def __init__(self, args): + self.args = args + + @abstractmethod + def filter(self, pkt): + pass + + +class RequiredTypeFilter(PacketInFilterBase): + + def filter(self, pkt): + required_types = self.args.get('types') or [] + for required_type in required_types: + if not pkt.get_protocol(required_type): + return False + return True diff --git a/ryu/tests/unit/lib/test_ofp_pktinfilter.py b/ryu/tests/unit/lib/test_ofp_pktinfilter.py new file mode 100644 index 00000000..6a77f056 --- /dev/null +++ b/ryu/tests/unit/lib/test_ofp_pktinfilter.py @@ -0,0 +1,100 @@ +# Copyright (C) 2013 Stratosphere Inc. +# +# 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. + +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import unittest +import logging + +from nose.tools import * + +from ryu.base import app_manager +from ryu.controller import ofp_event +from ryu.controller.handler import ( + set_ev_cls, + MAIN_DISPATCHER, +) +from ryu.lib.packet import vlan, ethernet, ipv4 +from ryu.lib.ofp_pktinfilter import packet_in_filter, RequiredTypeFilter +from ryu.lib import mac +from ryu.ofproto import ether, ofproto_v1_3, ofproto_v1_3_parser + + +LOG = logging.getLogger('test_pktinfilter') + + +class _Datapath(object): + ofproto = ofproto_v1_3 + ofproto_parser = ofproto_v1_3_parser + + +class _PacketInFilterApp(app_manager.RyuApp): + + def __init__(self, *args, **kwargs): + super(_PacketInFilterApp, self).__init__(*args, **kwargs) + + @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) + @packet_in_filter(RequiredTypeFilter, {'types': [ + vlan.vlan, + ]}) + def packet_in_handler(self, ev): + return True + + +class Test_packet_in_filter(unittest.TestCase): + + """ Test case for pktinfilter + """ + + def setUp(self): + self.app = _PacketInFilterApp() + + def tearDown(self): + pass + + def test_pkt_in_filter_pass(self): + datapath = _Datapath() + e = ethernet.ethernet(mac.BROADCAST_STR, + mac.BROADCAST_STR, + ether.ETH_TYPE_8021Q) + v = vlan.vlan() + i = ipv4.ipv4() + pkt = (e / v / i) + pkt.serialize() + pkt_in = ofproto_v1_3_parser.OFPPacketIn(datapath, + data=buffer(pkt.data)) + ev = ofp_event.EventOFPPacketIn(pkt_in) + ok_(self.app.packet_in_handler(ev)) + + def test_pkt_in_filter_discard(self): + datapath = _Datapath() + e = ethernet.ethernet(mac.BROADCAST_STR, + mac.BROADCAST_STR, + ether.ETH_TYPE_IP) + i = ipv4.ipv4() + pkt = (e / i) + pkt.serialize() + pkt_in = ofproto_v1_3_parser.OFPPacketIn(datapath, + data=buffer(pkt.data)) + ev = ofp_event.EventOFPPacketIn(pkt_in) + ok_(not self.app.packet_in_handler(ev)) + + def test_pkt_in_filter_truncated(self): + datapath = _Datapath() + truncated_data = buffer('') + pkt_in = ofproto_v1_3_parser.OFPPacketIn(datapath, + data=truncated_data) + ev = ofp_event.EventOFPPacketIn(pkt_in) + ok_(not self.app.packet_in_handler(ev)) |