From 4652cd11938b7ed2ad16cbb80698caa44b0e53bb Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Mon, 15 Sep 2014 17:36:06 +0200 Subject: hash:mac type added to ipset --- kernel/net/netfilter/ipset/Kbuild | 2 +- kernel/net/netfilter/ipset/Kconfig | 9 ++ kernel/net/netfilter/ipset/ip_set_hash_gen.h | 11 +- kernel/net/netfilter/ipset/ip_set_hash_mac.c | 173 +++++++++++++++++++++++++++ lib/Makefile.am | 1 + lib/ipset_hash_mac.c | 140 ++++++++++++++++++++++ tests/hash:mac.t | 53 ++++++++ tests/hash:mac.t.list0 | 7 ++ tests/hash:mac.t.list1 | 12 ++ tests/hash:mac.t.list2 | 8 ++ tests/runtest.sh | 2 +- tests/setlist_resize.sh | 2 +- 12 files changed, 416 insertions(+), 4 deletions(-) create mode 100644 kernel/net/netfilter/ipset/ip_set_hash_mac.c create mode 100644 lib/ipset_hash_mac.c create mode 100644 tests/hash:mac.t create mode 100644 tests/hash:mac.t.list0 create mode 100644 tests/hash:mac.t.list1 create mode 100644 tests/hash:mac.t.list2 diff --git a/kernel/net/netfilter/ipset/Kbuild b/kernel/net/netfilter/ipset/Kbuild index 6495523..33b663e 100644 --- a/kernel/net/netfilter/ipset/Kbuild +++ b/kernel/net/netfilter/ipset/Kbuild @@ -7,7 +7,7 @@ obj-m += ip_set_bitmap_ip.o ip_set_bitmap_ipmac.o ip_set_bitmap_port.o obj-m += ip_set_hash_ip.o ip_set_hash_ipport.o ip_set_hash_ipportip.o obj-m += ip_set_hash_ipportnet.o ip_set_hash_ipmark.o obj-m += ip_set_hash_net.o ip_set_hash_netport.o ip_set_hash_netiface.o -obj-m += ip_set_hash_netnet.o ip_set_hash_netportnet.o +obj-m += ip_set_hash_netnet.o ip_set_hash_netportnet.o ip_set_hash_mac.o obj-m += ip_set_list_set.o # It's for me... diff --git a/kernel/net/netfilter/ipset/Kconfig b/kernel/net/netfilter/ipset/Kconfig index 638faa7..af1017c 100644 --- a/kernel/net/netfilter/ipset/Kconfig +++ b/kernel/net/netfilter/ipset/Kconfig @@ -99,6 +99,15 @@ config IP_SET_HASH_IPPORTNET To compile it as a module, choose M here. If unsure, say N. +config IP_SET_HASH_MAC + tristate "hash:mac set support" + depends on IP_SET + help + This option adds the hash:mac set type support, by which + one can store MAC (ethernet address) elements in a set. + + To compile it as a module, choose M here. If unsure, say N. + config IP_SET_HASH_NETPORTNET tristate "hash:net,port,net set support" depends on IP_SET diff --git a/kernel/net/netfilter/ipset/ip_set_hash_gen.h b/kernel/net/netfilter/ipset/ip_set_hash_gen.h index c465907..1ab3339 100644 --- a/kernel/net/netfilter/ipset/ip_set_hash_gen.h +++ b/kernel/net/netfilter/ipset/ip_set_hash_gen.h @@ -1054,8 +1054,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, struct HTYPE *h; struct htable *t; +#ifndef IP_SET_PROTO_UNDEF if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) return -IPSET_ERR_INVALID_FAMILY; +#endif #ifdef IP_SET_HASH_WITH_MARKMASK markmask = 0xffffffff; @@ -1137,25 +1139,32 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, rcu_assign_pointer(h->table, t); set->data = h; +#ifndef IP_SET_PROTO_UNDEF if (set->family == NFPROTO_IPV4) { +#endif set->variant = &IPSET_TOKEN(HTYPE, 4_variant); set->dsize = ip_set_elem_len(set, tb, sizeof(struct IPSET_TOKEN(HTYPE, 4_elem))); +#ifndef IP_SET_PROTO_UNDEF } else { set->variant = &IPSET_TOKEN(HTYPE, 6_variant); set->dsize = ip_set_elem_len(set, tb, sizeof(struct IPSET_TOKEN(HTYPE, 6_elem))); } +#endif if (tb[IPSET_ATTR_TIMEOUT]) { set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); +#ifndef IP_SET_PROTO_UNDEF if (set->family == NFPROTO_IPV4) +#endif IPSET_TOKEN(HTYPE, 4_gc_init)(set, IPSET_TOKEN(HTYPE, 4_gc)); +#ifndef IP_SET_PROTO_UNDEF else IPSET_TOKEN(HTYPE, 6_gc_init)(set, IPSET_TOKEN(HTYPE, 6_gc)); +#endif } - pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", set->name, jhash_size(t->htable_bits), t->htable_bits, h->maxelem, set->data, t); diff --git a/kernel/net/netfilter/ipset/ip_set_hash_mac.c b/kernel/net/netfilter/ipset/ip_set_hash_mac.c new file mode 100644 index 0000000..65690b5 --- /dev/null +++ b/kernel/net/netfilter/ipset/ip_set_hash_mac.c @@ -0,0 +1,173 @@ +/* Copyright (C) 2014 Jozsef Kadlecsik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* Kernel module implementing an IP set type: the hash:mac type */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define IPSET_TYPE_REV_MIN 0 +#define IPSET_TYPE_REV_MAX 0 + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jozsef Kadlecsik "); +IP_SET_MODULE_DESC("hash:mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); +MODULE_ALIAS("ip_set_hash:mac"); + +/* Type specific function prefix */ +#define HTYPE hash_mac + +/* Member elements */ +struct hash_mac4_elem { + /* Zero valued IP addresses cannot be stored */ + union { + unsigned char ether[ETH_ALEN]; + __be32 foo[2]; + }; +}; + +/* Common functions */ + +static inline bool +hash_mac4_data_equal(const struct hash_mac4_elem *e1, + const struct hash_mac4_elem *e2, + u32 *multi) +{ + return ether_addr_equal(e1->ether, e2->ether); +} + +static inline bool +hash_mac4_data_list(struct sk_buff *skb, const struct hash_mac4_elem *e) +{ + return nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, e->ether); +} + +static inline void +hash_mac4_data_next(struct hash_mac4_elem *next, + const struct hash_mac4_elem *e) +{ +} + +#define MTYPE hash_mac4 +#define PF 4 +#define HOST_MASK 32 +#define IP_SET_EMIT_CREATE +#define IP_SET_PROTO_UNDEF +#include "ip_set_hash_gen.h" + +/* Zero valued element is not supported */ +static const unsigned char invalid_ether[ETH_ALEN] = { 0 }; + +static int +hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb, + const struct xt_action_param *par, + enum ipset_adt adt, struct ip_set_adt_opt *opt) +{ + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } }; + struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); + + /* MAC can be src only */ + if (!(opt->flags & IPSET_DIM_ONE_SRC)) + return 0; + + if (skb_mac_header(skb) < skb->head || + (skb_mac_header(skb) + ETH_HLEN) > skb->data) + return -EINVAL; + + memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN); + if (memcmp(e.ether, invalid_ether, ETH_ALEN) == 0) + return -EINVAL; + return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); +} + +static int +hash_mac4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) +{ + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); + int ret; + + if (unlikely(!tb[IPSET_ATTR_ETHER] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE))) + return -IPSET_ERR_PROTOCOL; + + if (tb[IPSET_ATTR_LINENO]) + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); + + ret = ip_set_get_extensions(set, tb, &ext); + if (ret) + return ret; + memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN); + if (memcmp(e.ether, invalid_ether, ETH_ALEN) == 0) + return -IPSET_ERR_HASH_ELEM; + + return adtfn(set, &e, &ext, &ext, flags); +} + +static struct ip_set_type hash_mac_type __read_mostly = { + .name = "hash:mac", + .protocol = IPSET_PROTOCOL, + .features = IPSET_TYPE_MAC, + .dimension = IPSET_DIM_ONE, + .family = NFPROTO_UNSPEC, + .revision_min = IPSET_TYPE_REV_MIN, + .revision_max = IPSET_TYPE_REV_MAX, + .create = hash_mac_create, + .create_policy = { + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_ETHER] = { .type = NLA_BINARY, + .len = ETH_ALEN }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, + [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, + [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, + [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, + [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, + [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, + }, + .me = THIS_MODULE, +}; + +static int __init +hash_mac_init(void) +{ + return ip_set_type_register(&hash_mac_type); +} + +static void __exit +hash_mac_fini(void) +{ + ip_set_type_unregister(&hash_mac_type); +} + +module_init(hash_mac_init); +module_exit(hash_mac_fini); diff --git a/lib/Makefile.am b/lib/Makefile.am index 053e855..36f60b0 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,6 +14,7 @@ IPSET_SETTYPE_LIST = \ ipset_hash_netportnet.c \ ipset_hash_netport.c \ ipset_hash_netiface.c \ + ipset_hash_mac.c \ ipset_list_set.c AM_CFLAGS += ${libmnl_CFLAGS} diff --git a/lib/ipset_hash_mac.c b/lib/ipset_hash_mac.c new file mode 100644 index 0000000..30be160 --- /dev/null +++ b/lib/ipset_hash_mac.c @@ -0,0 +1,140 @@ +/* Copyright 2014 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include /* IPSET_OPT_* */ +#include /* parser functions */ +#include /* printing functions */ +#include /* prototypes */ + +/* Parse commandline arguments */ +static const struct ipset_arg hash_mac_create_args0[] = { + { .name = { "hashsize", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE, + .parse = ipset_parse_uint32, .print = ipset_print_number, + }, + { .name = { "maxelem", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM, + .parse = ipset_parse_uint32, .print = ipset_print_number, + }, + { .name = { "timeout", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, + .parse = ipset_parse_timeout, .print = ipset_print_number, + }, + { .name = { "counters", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_COUNTERS, + .parse = ipset_parse_flag, .print = ipset_print_flag, + }, + { .name = { "comment", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_CREATE_COMMENT, + .parse = ipset_parse_flag, .print = ipset_print_flag, + }, + { .name = { "forceadd", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FORCEADD, + .parse = ipset_parse_flag, .print = ipset_print_flag, + }, + { .name = { "skbinfo", NULL }, + .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_SKBINFO, + .parse = ipset_parse_flag, .print = ipset_print_flag, + }, + { }, +}; + +static const struct ipset_arg hash_mac_add_args0[] = { + { .name = { "timeout", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT, + .parse = ipset_parse_timeout, .print = ipset_print_number, + }, + { .name = { "packets", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PACKETS, + .parse = ipset_parse_uint64, .print = ipset_print_number, + }, + { .name = { "bytes", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_BYTES, + .parse = ipset_parse_uint64, .print = ipset_print_number, + }, + { .name = { "comment", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_ADT_COMMENT, + .parse = ipset_parse_comment, .print = ipset_print_comment, + }, + { .name = { "skbmark", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_SKBMARK, + .parse = ipset_parse_skbmark, .print = ipset_print_skbmark, + }, + { .name = { "skbprio", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_SKBPRIO, + .parse = ipset_parse_skbprio, .print = ipset_print_skbprio, + }, + { .name = { "skbqueue", NULL }, + .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_SKBQUEUE, + .parse = ipset_parse_uint16, .print = ipset_print_number, + }, + { }, +}; + + +static const char hash_mac_usage0[] = +"create SETNAME hash:mac\n" +" [hashsize VALUE] [maxelem VALUE]\n" +" [timeout VALUE]\n" +" [counters] [comment] [forceadd] [skbinfo]\n" +"add SETNAME MAC [timeout VALUE]\n" +" [packets VALUE] [bytes VALUE] [comment \"string\"]\n" +" [skbmark VALUE] [skbprio VALUE] [skbqueue VALUE]\n" +"del SETNAME MAC\n" +"test SETNAME MAC\n"; + +static struct ipset_type ipset_hash_mac0 = { + .name = "hash:mac", + .alias = { "machash", NULL }, + .revision = 0, + .family = NFPROTO_UNSPEC, + .dimension = IPSET_DIM_ONE, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ether, + .print = ipset_print_ether, + .opt = IPSET_OPT_ETHER + }, + }, + .args = { + [IPSET_CREATE] = hash_mac_create_args0, + [IPSET_ADD] = hash_mac_add_args0, + }, + .mandatory = { + [IPSET_CREATE] = 0, + [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_ETHER), + [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_ETHER), + [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_ETHER), + }, + .full = { + [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE) + | IPSET_FLAG(IPSET_OPT_MAXELEM) + | IPSET_FLAG(IPSET_OPT_TIMEOUT) + | IPSET_FLAG(IPSET_OPT_COUNTERS) + | IPSET_FLAG(IPSET_OPT_CREATE_COMMENT) + | IPSET_FLAG(IPSET_OPT_FORCEADD) + | IPSET_FLAG(IPSET_OPT_SKBINFO), + [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_ETHER) + | IPSET_FLAG(IPSET_OPT_TIMEOUT) + | IPSET_FLAG(IPSET_OPT_PACKETS) + | IPSET_FLAG(IPSET_OPT_BYTES) + | IPSET_FLAG(IPSET_OPT_ADT_COMMENT) + | IPSET_FLAG(IPSET_OPT_SKBMARK) + | IPSET_FLAG(IPSET_OPT_SKBPRIO) + | IPSET_FLAG(IPSET_OPT_SKBQUEUE), + [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_ETHER), + [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_ETHER), + }, + + .usage = hash_mac_usage0, + .description = "Initial revision", +}; + +void _init(void); +void _init(void) +{ + ipset_type_add(&ipset_hash_mac0); +} diff --git a/tests/hash:mac.t b/tests/hash:mac.t new file mode 100644 index 0000000..25739da --- /dev/null +++ b/tests/hash:mac.t @@ -0,0 +1,53 @@ +# MAC: Create a set with timeout +0 ipset -N test machash --hashsize 128 timeout 5 +# Range: Add zero valued element +1 ipset -A test 0:0:0:0:0:0 +# Range: Test zero valued element +1 ipset -T test 0:0:0:0:0:0 +# MAC: Add first random value +0 ipset -A test 0:0:0:0:2:0 timeout 5 +# MAC: Add second random value +0 ipset -A test 0:a:0:0:0:0 timeout 0 +# MAC: Test first random value +0 ipset -T test 0:0:0:0:2:0 +# MAC: Test second random value +0 ipset -T test 0:a:0:0:0:0 +# MAC: Test value not added to the set +1 ipset -T test 0:0:0:0:1:0 +# MAC: Add third random value +0 ipset -A test 1:2:3:4:a:b +# MAC: Delete the same value +0 ipset -D test 1:2:3:4:a:b +# MAC: List set +0 ipset -L test | grep -v Revision: | sed 's/timeout ./timeout x/' > .foo0 && ./sort.sh .foo0 +# MAC: Check listing +0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list2 +# Sleep 5s so that element can time out +0 sleep 5 +# MAC: List set +0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +# MAC: Check listing +0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list0 +# MAC: Destroy test set +0 ipset -X test +# MAC: Create a set with skbinfo extension +0 ipset n test hash:mac skbinfo +# MAC: Add element with mark +0 ipset a test 1:2:3:4:5:6 skbmark 0x123456 +# MAC: Add element with mark/mask +0 ipset a test 1:2:3:4:5:7 skbmark 0x1234ab/0x0000ffff +# MAC: Add element with skbprio +0 ipset a test 1:2:3:4:5:8 skbprio 1:20 +# MAC: Add element with skbqueue +0 ipset a test 1:2:3:4:5:9 skbqueue 11 +# MAC: Add element with mark and skbprio +0 ipset a test 1:2:3:4:5:10 skbmark 0xaabbccdd skbprio 22:1 +# MAC: Add element with mark, skbprio and skbqueue +0 ipset a test 1:2:3:4:5:11 skbmark 0x11223344/0xffff0000 skbprio 2:1 skbqueue 8 +# MAC: List set +0 ipset -L test 2>/dev/null | grep -v Revision: > .foo0 && ./sort.sh .foo0 +# MAC: Check listing +0 diff -u -I 'Size in memory.*' .foo hash:mac.t.list1 +# MAC: Destroy test set +0 ipset -X test +# eof diff --git a/tests/hash:mac.t.list0 b/tests/hash:mac.t.list0 new file mode 100644 index 0000000..c2bbfd6 --- /dev/null +++ b/tests/hash:mac.t.list0 @@ -0,0 +1,7 @@ +Name: test +Type: hash:mac +Header: hashsize 128 maxelem 65536 timeout 5 +Size in memory: 2488 +References: 0 +Members: +00:0A:00:00:00:00 timeout 0 diff --git a/tests/hash:mac.t.list1 b/tests/hash:mac.t.list1 new file mode 100644 index 0000000..185f35f --- /dev/null +++ b/tests/hash:mac.t.list1 @@ -0,0 +1,12 @@ +Name: test +Type: hash:mac +Header: hashsize 1024 maxelem 65536 skbinfo +Size in memory: 17304 +References: 0 +Members: +01:02:03:04:05:06 skbmark 0x123456 +01:02:03:04:05:07 skbmark 0x1234ab/0xffff +01:02:03:04:05:08 skbprio 1:20 +01:02:03:04:05:09 skbqueue 11 +01:02:03:04:05:10 skbmark 0xaabbccdd skbprio 22:1 +01:02:03:04:05:11 skbmark 0x11223344/0xffff0000 skbprio 2:1 skbqueue 8 diff --git a/tests/hash:mac.t.list2 b/tests/hash:mac.t.list2 new file mode 100644 index 0000000..2bec98d --- /dev/null +++ b/tests/hash:mac.t.list2 @@ -0,0 +1,8 @@ +Name: test +Type: hash:mac +Header: hashsize 128 maxelem 65536 timeout x +Size in memory: 2488 +References: 0 +Members: +00:00:00:00:02:00 timeout x +00:0A:00:00:00:00 timeout x diff --git a/tests/runtest.sh b/tests/runtest.sh index fbfa154..05550c6 100755 --- a/tests/runtest.sh +++ b/tests/runtest.sh @@ -14,7 +14,7 @@ tests="$tests ipportiphash hash:ip,port,ip hash:ip6,port,ip6" tests="$tests nethash hash:net hash:net6 hash:net,port hash:net6,port" tests="$tests hash:ip,port,net hash:ip6,port,net6 hash:net,net hash:net6,net6" tests="$tests hash:net,port,net hash:net6,port,net6" -tests="$tests hash:net,iface.t" +tests="$tests hash:net,iface.t hash:mac.t" tests="$tests comment setlist restore" # tests="$tests iptree iptreemap" diff --git a/tests/setlist_resize.sh b/tests/setlist_resize.sh index 01d1cfc..3255656 100755 --- a/tests/setlist_resize.sh +++ b/tests/setlist_resize.sh @@ -9,7 +9,7 @@ loop=8 for x in ip_set_list_set ip_set_hash_netiface ip_set_hash_ipportnet \ ip_set_hash_netport ip_set_hash_net ip_set_hash_ipportip \ ip_set_hash_ipport ip_set_hash_ip ip_set_hash_netnet \ - ip_set_hash_netportnet ip_set_hash_ipmark \ + ip_set_hash_netportnet ip_set_hash_ipmark ip_set_hash_mac \ ip_set_bitmap_port ip_set_bitmap_ipmac \ ip_set_bitmap_ip xt_set ip_set; do rmmod $x -- cgit v1.2.3