diff --git a/gns3server/compute/base_node.py b/gns3server/compute/base_node.py index c80d5bea..b4dbc216 100644 --- a/gns3server/compute/base_node.py +++ b/gns3server/compute/base_node.py @@ -605,13 +605,24 @@ class BaseNode: yield from self._ubridge_send('bridge reset_packet_filters ' + bridge_name) i = 0 for (filter_type, values) in filters.items(): - cmd = "bridge add_packet_filter {bridge_name} {filter_name} {filter_type} {filter_value}".format( - bridge_name=bridge_name, - filter_name="filter" + str(i), - filter_type=filter_type, - filter_value=" ".join([str(v) for v in values])) - yield from self._ubridge_send(cmd) - i += 1 + if isinstance(values[0], str): + for line in values[0].split('\n'): + line = line.strip() + cmd = "bridge add_packet_filter {bridge_name} {filter_name} {filter_type} {filter_value}".format( + bridge_name=bridge_name, + filter_name="filter" + str(i), + filter_type=filter_type, + filter_value='"{}" {}'.format(line, " ".join([str(v) for v in values[1:]]))).strip() + yield from self._ubridge_send(cmd) + i += 1 + else: + cmd = "bridge add_packet_filter {bridge_name} {filter_name} {filter_type} {filter_value}".format( + bridge_name=bridge_name, + filter_name="filter" + str(i), + filter_type=filter_type, + filter_value=" ".join([str(v) for v in values])) + yield from self._ubridge_send(cmd) + i += 1 @asyncio.coroutine def _add_ubridge_ethernet_connection(self, bridge_name, ethernet_interface, block_host_traffic=True): diff --git a/gns3server/controller/link.py b/gns3server/controller/link.py index 9e202bfb..8ad81fd0 100644 --- a/gns3server/controller/link.py +++ b/gns3server/controller/link.py @@ -36,6 +36,7 @@ FILTERS = [ "name": "Frequency", "minimum": -1, "maximum": 32767, + "type": "int", "unit": "th packet" } ] @@ -49,6 +50,7 @@ FILTERS = [ "name": "Chance", "minimum": 0, "maximum": 100, + "type": "int", "unit": "%" } ] @@ -62,13 +64,15 @@ FILTERS = [ "name": "Latency", "minimum": 0, "maximum": 32767, - "unit": "ms" + "unit": "ms", + "type": "int" }, { "name": "Jitter (-/+)", "minimum": 0, "maximum": 32767, - "unit": "ms" + "unit": "ms", + "type": "int" } ] }, @@ -81,7 +85,19 @@ FILTERS = [ "name": "Chance", "minimum": 0, "maximum": 100, - "unit": "%" + "unit": "%", + "type": "int" + } + ] + }, + { + "type": "bpf", + "name": "BPF", + "description": "Berkeley Packet Filter (BPF) syntax. This filter will drop any packet matching the expression. Put one filter by line", + "parameters": [ + { + "name": "BPF filters", + "type": "text" } ] } @@ -124,8 +140,14 @@ class Link: """ new_filters = {} for (filter, values) in filters.items(): - values = [int(v) for v in values] - if len(values) != 0 and values[0] != 0: + new_values = [] + for value in values: + if isinstance(value, str): + new_values.append(value.strip("\n ")) + else: + new_values.append(int(value)) + values = new_values + if len(values) != 0 and values[0] != 0 and values[0] != '': new_filters[filter] = values if new_filters != self.filters: diff --git a/tests/compute/test_base_node.py b/tests/compute/test_base_node.py index e42f3e98..e942c698 100644 --- a/tests/compute/test_base_node.py +++ b/tests/compute/test_base_node.py @@ -139,9 +139,21 @@ def test_update_ubridge_udp_connection(node, async_run): def test_ubridge_apply_filters(node, async_run): filters = { - "latency": [10] + "latency": [10], + "bpf": ["icmp[icmptype] == 8\ntcp src port 53"] } node._ubridge_send = AsyncioMagicMock() async_run(node._ubridge_apply_filters("VPCS-10", filters)) node._ubridge_send.assert_any_call("bridge reset_packet_filters VPCS-10") node._ubridge_send.assert_any_call("bridge add_packet_filter VPCS-10 filter0 latency 10") + + +def test_ubridge_apply_bpf_filters(node, async_run): + filters = { + "bpf": ["icmp[icmptype] == 8\ntcp src port 53"] + } + node._ubridge_send = AsyncioMagicMock() + async_run(node._ubridge_apply_filters("VPCS-10", filters)) + node._ubridge_send.assert_any_call("bridge reset_packet_filters VPCS-10") + node._ubridge_send.assert_any_call("bridge add_packet_filter VPCS-10 filter0 bpf \"icmp[icmptype] == 8\"") + node._ubridge_send.assert_any_call("bridge add_packet_filter VPCS-10 filter1 bpf \"tcp src port 53\"") diff --git a/tests/controller/test_link.py b/tests/controller/test_link.py index 24638fdb..42015b08 100644 --- a/tests/controller/test_link.py +++ b/tests/controller/test_link.py @@ -369,9 +369,10 @@ def test_update_filters(async_run, project, compute): link.update = AsyncioMagicMock() assert link._created async_run(link.update_filters({ - "packet_loss": ["10"], - "delay": ["50", "10"], - "frequency_drop": ["0"] + "packet_loss": [10], + "delay": [50, 10], + "frequency_drop": [0], + "bpf": [" \n "] })) assert link.filters == { "packet_loss": [10], diff --git a/tests/controller/test_udp_link.py b/tests/controller/test_udp_link.py index 3ab6581f..5c738b4b 100644 --- a/tests/controller/test_udp_link.py +++ b/tests/controller/test_udp_link.py @@ -373,11 +373,14 @@ def test_update(async_run, project): }, timeout=120) assert link.created - async_run(link.update_filters({"drop": [5]})) + async_run(link.update_filters({"drop": [5], "bpf": ["icmp[icmptype] == 8"]})) compute1.put.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={ "lport": 1024, "rhost": "192.168.1.2", "rport": 2048, "type": "nio_udp", - "filters": {"drop": [5]} + "filters": { + "drop": [5], + "bpf": ["icmp[icmptype] == 8"] + } }, timeout=120)