return f"""if (ip6 == NULL) break;
if (!( {ast.write("((((uint32_t)(ip6->flow_lbl[0] & 0xf)) << 2*8) | (((uint32_t)ip6->flow_lbl[1]) << 1*8) | (uint32_t)ip6->flow_lbl[0])")} )) break;"""
+
with open("rules.h", "w") as out:
parse = argparse.ArgumentParser()
parse.add_argument("--ihl", dest="ihl", required=True, choices=["drop-options","accept-options","parse-options"])
use_v6_frags = False
rulecnt = 0
+ lastrule = None
for line in sys.stdin.readlines():
- t = line.split("{")
- if len(t) != 2:
- continue
- if t[0].strip() == "flow4":
- proto = 4
- rules4 += "\tdo {\\\n"
- elif t[0].strip() == "flow6":
- proto = 6
- rules6 += "\tdo {\\\n"
- else:
+ if "{" in line:
+ if lastrule is not None:
+ print("Skipped rule due to lack of understood community tag: " + lastrule)
+ lastrule = line
continue
-
- def write_rule(r):
- global rules4, rules6
- if proto == 6:
- rules6 += "\t\t" + r.replace("\n", " \\\n\t\t") + " \\\n"
+ if "BGP.ext_community: " in line:
+ assert lastrule is not None
+
+ t = lastrule.split("{")
+ if t[0].strip() == "flow4":
+ proto = 4
+ rules4 += "\tdo {\\\n"
+ elif t[0].strip() == "flow6":
+ proto = 6
+ rules6 += "\tdo {\\\n"
else:
- rules4 += "\t\t" + r.replace("\n", " \\\n\t\t") + " \\\n"
-
- rule = t[1].split("}")[0].strip()
- for step in rule.split(";"):
- if step.strip().startswith("src") or step.strip().startswith("dst"):
- nets = step.strip()[3:].strip().split(" ")
- if len(nets) > 1:
- assert nets[1] == "offset"
- offset = nets[2]
+ continue
+
+ def write_rule(r):
+ global rules4, rules6
+ if proto == 6:
+ rules6 += "\t\t" + r.replace("\n", " \\\n\t\t") + " \\\n"
else:
- offset = None
- if step.strip().startswith("src"):
- write_rule(ip_to_rule(proto, nets[0], "saddr", offset))
+ rules4 += "\t\t" + r.replace("\n", " \\\n\t\t") + " \\\n"
+
+ rule = t[1].split("}")[0].strip()
+ for step in rule.split(";"):
+ if step.strip().startswith("src") or step.strip().startswith("dst"):
+ nets = step.strip()[3:].strip().split(" ")
+ if len(nets) > 1:
+ assert nets[1] == "offset"
+ offset = nets[2]
+ else:
+ offset = None
+ if step.strip().startswith("src"):
+ write_rule(ip_to_rule(proto, nets[0], "saddr", offset))
+ else:
+ write_rule(ip_to_rule(proto, nets[0], "daddr", offset))
+ elif step.strip().startswith("proto") and proto == 4:
+ write_rule(proto_to_rule(4, step.strip()[6:]))
+ elif step.strip().startswith("next header") and proto == 6:
+ write_rule(proto_to_rule(6, step.strip()[12:]))
+ elif step.strip().startswith("icmp type"):
+ write_rule(icmp_type_to_rule(proto, step.strip()[10:]))
+ elif step.strip().startswith("icmp code"):
+ write_rule(icmp_code_to_rule(proto, step.strip()[10:]))
+ elif step.strip().startswith("sport") or step.strip().startswith("dport") or step.strip().startswith("port"):
+ write_rule(port_to_rule(step.strip().split(" ")[0], step.strip().split(" ", 1)[1]))
+ elif step.strip().startswith("length"):
+ write_rule(len_to_rule(step.strip()[7:]))
+ elif step.strip().startswith("dscp"):
+ write_rule(dscp_to_rule(proto, step.strip()[5:]))
+ elif step.strip().startswith("tcp flags"):
+ write_rule(tcp_flags_to_rule(step.strip()[10:]))
+ elif step.strip().startswith("label"):
+ write_rule(flow_label_to_rule(step.strip()[6:]))
+ elif step.strip().startswith("fragment"):
+ if proto == 6:
+ use_v6_frags = True
+ write_rule(fragment_to_rule(proto, step.strip()[9:]))
+ elif step.strip() == "":
+ pass
else:
- write_rule(ip_to_rule(proto, nets[0], "daddr", offset))
- elif step.strip().startswith("proto") and proto == 4:
- write_rule(proto_to_rule(4, step.strip()[6:]))
- elif step.strip().startswith("next header") and proto == 6:
- write_rule(proto_to_rule(6, step.strip()[12:]))
- elif step.strip().startswith("icmp type"):
- write_rule(icmp_type_to_rule(proto, step.strip()[10:]))
- elif step.strip().startswith("icmp code"):
- write_rule(icmp_code_to_rule(proto, step.strip()[10:]))
- elif step.strip().startswith("sport") or step.strip().startswith("dport") or step.strip().startswith("port"):
- write_rule(port_to_rule(step.strip().split(" ")[0], step.strip().split(" ", 1)[1]))
- elif step.strip().startswith("length"):
- write_rule(len_to_rule(step.strip()[7:]))
- elif step.strip().startswith("dscp"):
- write_rule(dscp_to_rule(proto, step.strip()[5:]))
- elif step.strip().startswith("tcp flags"):
- write_rule(tcp_flags_to_rule(step.strip()[10:]))
- elif step.strip().startswith("label"):
- write_rule(flow_label_to_rule(step.strip()[6:]))
- elif step.strip().startswith("fragment"):
- if proto == 6:
- use_v6_frags = True
- write_rule(fragment_to_rule(proto, step.strip()[9:]))
- elif step.strip() == "":
- pass
+ assert False
+
+ # Now write the match handling!
+ first_action = None
+ last_action = None
+ for community in line.split("("):
+ if not community.startswith("generic, "):
+ continue
+ blocks = community.split(",")
+ assert len(blocks) == 3
+ if len(blocks[1].strip()) != 10: # Should be 0x12345678
+ continue
+ ty = blocks[1].strip()[:6]
+ low_bytes = int(blocks[2].strip(") \n"), 16)
+ if ty == "0x8006":
+ if low_bytes == 0:
+ first_action = "return XDP_DROP;"
+ else:
+ assert False # Not yet supported
+ elif ty == "0x8007":
+ if low_bytes & 1 == 0:
+ last_action = "return XDP_PASS;"
+ if low_bytes & 2 == 2:
+ write_rule(f"const uint32_t ruleidx = STATIC_RULE_CNT + {rulecnt};")
+ write_rule("INCREMENT_MATCH(ruleidx);")
+ elif ty == "0x8008":
+ assert False # We do not implement the redirect action
+ elif ty == "0x8009":
+ if low_bytes & ~0b111111 != 0:
+ assert False # Invalid DSCP value
+ if proto == 4:
+ write_rule("int32_t chk = ~BE16(ip->check) & 0xffff;")
+ write_rule("uint8_t orig_tos = ip->tos;")
+ write_rule("ip->tos = (ip->tos & 3) | " + str(low_bytes << 2) + ";")
+ write_rule("chk = (chk - orig_tos + ip->tos);")
+ write_rule("if (unlikely(chk < 0)) { chk += 65534; }")
+ write_rule("ip->check = ~BE16(chk);")
+ else:
+ write_rule("ip6->priority = " + str(low_bytes >> 2) + ";")
+ write_rule("ip6->flow_lbl[0] = (ip6->flow_lbl[0] & 0x3f) | " + str((low_bytes & 3) << 6) + ";")
+ if first_action is not None:
+ write_rule(first_action)
+ if last_action is not None:
+ write_rule(last_action)
+ if proto == 6:
+ rules6 += "\t} while(0);\\\n"
else:
- assert False
- write_rule(f"const uint32_t ruleidx = STATIC_RULE_CNT + {rulecnt};")
- write_rule("DO_RETURN(ruleidx, XDP_DROP);")
- if proto == 6:
- rules6 += "\t} while(0);\\\n"
- else:
- rules4 += "\t} while(0);\\\n"
- rulecnt += 1
+ rules4 += "\t} while(0);\\\n"
+ rulecnt += 1
+ lastrule = None
out.write("\n")
out.write(f"#define RULECNT {rulecnt}\n")
set -e
+COMMUNITY_DROP="
+ Type: static univ
+ BGP.ext_community: (generic, 0x80060000, 0x0) (generic, 0x80070000, 0xf) (generic, 0x80090000, 0x3f)"
+
TEST_PKT='#define TEST \
"\x00\x17\x10\x95\xe8\x96\x00\x0d\xb9\x50\x11\x4c\x08\x00\x45\x00" \
"\x00\x8c\x7d\x0f\x00\x00\x40\x11\x3a\x31\x48\xe5\x68\xce\x67\x63" \
"\xb5\xc3\xa9\xa6\x21\x14\xc7\xd9\x71\x07"'
# Test all the things...
-echo "flow4 { src 72.229.104.206/32; dst 103.99.170.10/32; proto = 17; sport = 56733; dport = 4242; length = 140; dscp = 0; fragment !dont_fragment && !is_fragment && !first_fragment && !last_fragment };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { src 72.229.104.206/32; dst 103.99.170.10/32; proto = 17; sport = 56733; dport = 4242; length = 140; dscp = 0; fragment !dont_fragment && !is_fragment && !first_fragment && !last_fragment };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { port = 4242; icmp code = 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow4 { port = 4242; icmp code = 0; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# Some port tests...
-echo "flow4 { port = 4242 && = 56733; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 4242 && = 56733; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { port = 4242 || 1; sport = 56733 };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 4242 || 1; sport = 56733 };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { port = 4242 && 1 };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow4 { port = 4242 && 1 };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# Some match-order tests...
# (43 && 42) || 4242
-echo "flow4 { port = 43 && 42, 4242; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 43 && 42, 4242; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# (43 && 42) || 4242
-echo "flow4 { port = 43 && 42 || 4242; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 43 && 42 || 4242; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# 4242 || (42 && 43)
-echo "flow4 { port = 4242, 42 && 43; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 4242, 42 && 43; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# (4242 && false) || (42 && 4242)
-echo "flow4 { port = 4242 && false, 42 && 4242; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 4242 && false, 42 && 4242; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# (4242 && true) || (42 && 43)
-echo "flow4 { port = 4242 && true, 42 && 43; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 4242 && true, 42 && 43; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# 42 || true
-echo "flow4 { port = 42, true; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow4 { port = 42, true; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow4 { icmp code != 0; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
"\x75\xde\xeb\x22\xd6\x80"'
# Some v6 TCP tests with a DSCP of all 1s...
-echo "flow6 { src 2a01:4f8:130:71d2::2/128; dst 2620:6e:a000:2001::6/128; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow6 { src 2a01:4f8:130:71d2::2/128; dst 2620:6e:a000:2001::6/128; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { src 0:4f8:130:71d2::2/128 offset 16; dst 0:0:a000:2001::/64 offset 32; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow6 { src 0:4f8:130:71d2::2/128 offset 16; dst 0:0:a000:2001::/64 offset 32; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { dscp 0x3f; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow6 { dscp 0x3f; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow6 { icmp code != 0; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
"\x32\x33\x34\x35\x36\x37"'
# ICMP and VLAN tests with DSCP of all 1s...
-echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --v6frag=ignore
+echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { icmp type 8; icmp code > 0; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
+echo "flow4 { icmp type 8; icmp code > 0; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { icmp type 9; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
+echo "flow4 { icmp type 9; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=3 --v6frag=ignore
+echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=3 --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { src 0.0.0.0/32; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=4 --v6frag=ignore
+echo "flow4 { src 0.0.0.0/32; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=4 --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { src 0.0.0.0/32; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --require-8021q=3 --v6frag=drop-frags
+echo "flow4 { src 0.0.0.0/32; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --require-8021q=3 --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { port 42; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
+echo "flow4 { port 42; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { dscp 0x3f; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow4 { dscp 0x3f; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# Test --8021q option handling
-echo "flow4 { port 42; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow4 { port 42; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow4 { };" | ./genrules.py --ihl=drop-options --8021q=accept-vlan --v6frag=drop-frags
+echo "flow4 { };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=accept-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
"\x00\x00\x00\x00\x00\x00"'
# ICMPv6 tests
-echo "flow6 { icmp type 129; icmp code 0; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow6 { icmp type 129; icmp code 0; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow6 { icmp code != 0; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { tcp flags 0x0/0x0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow6 { tcp flags 0x0/0x0; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { port 42; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow6 { port 42; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { fragment is_fragment || first_fragment || last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
+echo "flow6 { fragment is_fragment || first_fragment || last_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# Last frag ICMPv6 tests
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && !first_fragment && last_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && !first_fragment && last_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || first_fragment || !last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || first_fragment || !last_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || first_fragment || !last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || first_fragment || !last_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# Note on the second fragment we don't know the ICMP header (though < 256 is trivially true)
-echo "flow6 { icmp type < 256; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "flow6 { icmp type < 256; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
-clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
+clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -Wno-tautological-constant-out-of-range-compare -O0 -g xdp.c -o xdp && ./xdp
#TODO Is nextheader frag correct to match on here? Should we support matching on any nexthdr?
-echo "flow6 { next header 44; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
+echo "flow6 { next header 44; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# Test the --v6frag options (ignore-parse-if-rule is tested below)
-echo "flow6 { tcp flags 42/42; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
+echo "flow6 { tcp flags 42/42; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { tcp flags 42/42; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=drop-frags
+echo "flow6 { tcp flags 42/42; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=drop-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { tcp flags 42/42; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "flow6 { tcp flags 42/42; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# First frag ICMPv6 tests
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || !first_fragment || last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || !first_fragment || last_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; icmp code 0; icmp type 128 };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; icmp code 0; icmp type 128 };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
#TODO Is nextheader frag correct to match on here? Should we support matching on any nexthdr?
-echo "flow6 { next header 44; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
+echo "flow6 { next header 44; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
#TODO Is nextheader frag correct to match on here? Should we support matching on any nexthdr?
-echo "flow6 { next header 58; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "flow6 { next header 58; };$COMMUNITY_DROP" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
# Test accept-parse-if-rule
-echo "flow6 { icmp code 0; icmp type 128; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
+echo "flow6 { icmp code 0; icmp type 128; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { icmp code 0; icmp type 128; fragment is_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
+echo "flow6 { icmp code 0; icmp type 128; fragment is_fragment; };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_DROP" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
-echo "flow6 { icmp code 0; icmp type 128; fragment !is_fragment };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
+echo "flow6 { icmp code 0; icmp type 128; fragment !is_fragment };$COMMUNITY_DROP" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
echo "$TEST_PKT" >> rules.h
echo "#define TEST_EXP XDP_PASS" >> rules.h
clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp