It is noisy when a packet 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 <[email protected]> --- ryu/lib/pktinfilter.py | 57 ++++++++++++++++++ ryu/tests/unit/lib/test_pktinfilter.py | 100 ++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 0 deletions(-) create mode 100644 ryu/lib/pktinfilter.py create mode 100644 ryu/tests/unit/lib/test_pktinfilter.py diff --git a/ryu/lib/pktinfilter.py b/ryu/lib/pktinfilter.py new file mode 100644 index 0000000..c3bd979 --- /dev/null +++ b/ryu/lib/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_pktinfilter.py b/ryu/tests/unit/lib/test_pktinfilter.py new file mode 100644 index 0000000..e7d5bf1 --- /dev/null +++ b/ryu/tests/unit/lib/test_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.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)) -- 1.7.1 ------------------------------------------------------------------------------ Android is increasing in popularity, but the open development platform that developers love is also attractive to malware creators. Download this white paper to learn more about secure code signing practices that can help keep Android apps secure. http://pubads.g.doubleclick.net/gampad/clk?id=65839951&iu=/4140/ostg.clktrk _______________________________________________ Ryu-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ryu-devel
