diff --git a/src/apps/packet_filter/packet_filter.lua b/src/apps/packet_filter/packet_filter.lua index 11856c80bb..9debb8ae0a 100644 --- a/src/apps/packet_filter/packet_filter.lua +++ b/src/apps/packet_filter/packet_filter.lua @@ -611,6 +611,60 @@ function selftest () print ("state app_v4 failed") end + -- part 3: + app.configure(config.new()) + c = config.new() + + config.app(c, "source1", pcap.PcapReader, "apps/packet_filter/samples/v4-tcp-udp.pcap") + config.app(c, "stateless_pass1", PacketFilter, { + rules = { + { + ethertype = "ipv4", + dest_port_min = 12345, + protocol = "tcp", + }, + }, + }) + config.app(c, "sink1", basic_apps.Sink ) + config.link(c, "source1.output -> stateless_pass1.input") + config.link(c, "stateless_pass1.output -> sink1.input") + + app.configure(c) + app.breathe() + app.report() + + if app.app_table.stateless_pass1.output.output.stats.txpackets ~= 1 then + ok = false + print ("stateless tcp failed") + end + + app.configure(config.new()) + c = config.new() + + config.app(c, "source1", pcap.PcapReader, "apps/packet_filter/samples/v6-tcp-udp.pcap") + config.app(c, "stateless_pass1", PacketFilter, { + rules = { + { + ethertype = "ipv6", + dest_port_min = 1022, + protocol = "tcp", + }, + }, + }) + config.app(c, "sink1", basic_apps.Sink ) + config.link(c, "source1.output -> stateless_pass1.input") + config.link(c, "stateless_pass1.output -> sink1.input") + + app.configure(c) + app.breathe() + app.report() + + if app.app_table.stateless_pass1.output.output.stats.txpackets ~= 1 then + ok = false + print ("stateless v6 tcp failed") + end + + if not ok then print("selftest failed") os.exit(1) diff --git a/src/apps/packet_filter/samples/v4-tcp-udp.pcap b/src/apps/packet_filter/samples/v4-tcp-udp.pcap new file mode 100644 index 0000000000..3c9149c688 Binary files /dev/null and b/src/apps/packet_filter/samples/v4-tcp-udp.pcap differ diff --git a/src/apps/packet_filter/samples/v6-tcp-udp.pcap b/src/apps/packet_filter/samples/v6-tcp-udp.pcap new file mode 100644 index 0000000000..b69b32c72a Binary files /dev/null and b/src/apps/packet_filter/samples/v6-tcp-udp.pcap differ diff --git a/src/program/snabbnfv/fuzz/fuzz.lua b/src/program/snabbnfv/fuzz/fuzz.lua index 2896130c93..01c13934da 100644 --- a/src/program/snabbnfv/fuzz/fuzz.lua +++ b/src/program/snabbnfv/fuzz/fuzz.lua @@ -31,7 +31,7 @@ function fuzz_connective_ports (spec) for i = 1, n_rules do rules[i+2] = random_filter_rule() end - return rules + return { rules = rules } end local function fuzz_tunnel () local cookies = { random_cookie(), random_cookie() } diff --git a/src/program/snabbnfv/neutron2snabb/neutron2snabb.lua b/src/program/snabbnfv/neutron2snabb/neutron2snabb.lua index 453d533efa..7d8f1c5ea6 100644 --- a/src/program/snabbnfv/neutron2snabb/neutron2snabb.lua +++ b/src/program/snabbnfv/neutron2snabb/neutron2snabb.lua @@ -59,8 +59,8 @@ function create_config (input_dir, output_dir, hostname) { vlan = vif_details.zone_vlan, mac_address = port.mac_address, port_id = port.id, - ingress_filter = filter(port, secbindings, secrules, 'ingress'), - egress_filter = filter(port, secbindings, secrules, 'egress'), + ingress_filter = filter(port, secbindings, secrules, 'ingress', profile.packetfilter), + egress_filter = filter(port, secbindings, secrules, 'egress', profile.packetfilter), gbps = vif_details.zone_gbps, rx_police_gbps = profile.rx_police_gbps, tunnel = tunnel(port, vif_details, profile) }) @@ -77,7 +77,7 @@ function create_config (input_dir, output_dir, hostname) end -- Return the packet filter expression. -function filter (port, secbindings, secrules, direction) +function filter (port, secbindings, secrules, direction, type) local rules = {} direction = direction:lower() if secbindings[port.id] then @@ -95,9 +95,14 @@ function filter (port, secbindings, secrules, direction) end end end + if type == "stateless" then + return { rules = rules } + else + return { rules = rules, + state_track = port.id, + state_check = port.id } + end end - if #rules > 0 then return { rules = rules } - else return nil end end -- Return the L2TPv3 tunnel expresion. diff --git a/src/program/snabbnfv/selftest.sh b/src/program/snabbnfv/selftest.sh index 63c4302f54..a44de436fe 100755 --- a/src/program/snabbnfv/selftest.sh +++ b/src/program/snabbnfv/selftest.sh @@ -208,8 +208,8 @@ function test_rate_limited { # / on VM listening on . If `-u' is appended # UDP is used instead of TCP. function port_probe { - run_telnet $2 "nohup echo | nc $5 -l $3 $4 &" 2>&1 >/dev/null - run_telnet $1 "nc -v $5 $3 $4" 5 | agrep succeeded + run_telnet $2 "nohup echo | nc -q 1 $5 -l $3 $4 &" 2>&1 >/dev/null + run_telnet $1 "nc -w 1 -q 1 -v $5 $3 $4" 5 | agrep succeeded } function same_vlan_tests { @@ -285,8 +285,24 @@ function filter_tests { test 0 -ne $? assert FILTER $? - # Assert UDP/12345 is filtered. - port_probe $TELNET_PORT0 $TELNET_PORT1 "$GUEST_IP1%eth0" 12345 -u + + load_config program/snabbnfv/test_fixtures/nfvconfig/test_functions/stateful-filter.ports + + # port B allows ICMP and TCP/12345 ingress and established egress + # traffic. + + test_ping $TELNET_PORT0 "$GUEST_IP1%eth0" + + port_probe $TELNET_PORT0 $TELNET_PORT1 "$GUEST_IP1%eth0" 12345 + assert PORTPROBE $? + + # Assert TCP/12346 is filtered. + port_probe $TELNET_PORT0 $TELNET_PORT1 "$GUEST_IP1%eth0" 12348 + test 0 -ne $? + assert FILTER $? + + # Assert non-established egress connections are filtered. + port_probe $TELNET_PORT1 $TELNET_PORT0 "$GUEST_IP0%eth0" 12340 test 0 -ne $? assert FILTER $? } diff --git a/src/program/snabbnfv/test_fixtures/nfvconfig/test_functions/stateful-filter.ports b/src/program/snabbnfv/test_fixtures/nfvconfig/test_functions/stateful-filter.ports new file mode 100644 index 0000000000..88976ec4c0 --- /dev/null +++ b/src/program/snabbnfv/test_fixtures/nfvconfig/test_functions/stateful-filter.ports @@ -0,0 +1,19 @@ +return { + { vlan = 0, + mac_address = "52:54:00:00:00:00", + port_id = "A" + }, + { vlan = 0, + mac_address = "52:54:00:00:00:01", + port_id = "B", + ingress_filter = { rules = { { ethertype='ipv6', + protocol='icmp' }, + { ethertype='ipv6', + protocol='tcp', + dest_port_min=12345 } }, + state_track = "test" }, + egress_filter = { rules = { { ethertype='ipv6', + protocol='icmp' } }, + state_check = "test" } + }, +}