mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
netfilter pull request 24-08-23
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEN9lkrMBJgcdVAPub1V2XiooUIOQFAmbHtrsACgkQ1V2XiooU IOTZ8g/+OW8W468NmBHA2zrTWei19irA1iCBLvXMPakice0+ADU51eqVp6uUrCeP iBUZGMtCq4WzFBrAEBePK3UNxxMHquWvAsA0kO/XW95KVM++s9ykF62q89jugMb3 CADEv/TxgJrkzpLWclxHNTCWMKpURijlkjT+kCMR4fKbeQnB6e/jI+2sdl7l5iRG tHHm8ieewNNKE+jlSUJUrPEIM3tXRaZh9+JmbClfsF6wUw7qLmT/7P92aHBX4Owp tpqi/Xc5/2k+Ud96a8u1NYrLLG+L70uz3SaeE7PvhaRavFuYftk2XLB4L2umtEfb ZCZO/lCadH23XrVAUs5EtCDk4Tu3rZdTDsKYm2qS66uBsh/e6hg+j/cIPSO8jsNq 5Zbs/XzPFJ1PUpXVy8Sfs9vxH+cDuiqhy9nfKrbQotsqtoW+z52UoFH4WAjfmpqb XMI+yeSTXYl1KIo2LV408VFRFRGcstBvXE7bOn7ufSrltRZcFdx7wqQBgVbh1zvA 1NTzIguZ+Lf2hPcNLPQd/f2vghKRTI7gUwzlDRw6so6NOWUM6/yV5KyoiZKekHjC S6+M8cdiyMH8DmSsvAb46YKtDxYuIHqLVxuVqjfBHrMo1hLIo5smMCeCRA1Vabd5 /E4DTwpN5tVWX+HZl1wcAtQpXhcTktWM0qGSPnlRS11gwbAGWvk= =O8tu -----END PGP SIGNATURE----- Merge tag 'nf-next-24-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following batch contains Netfilter updates for net-next: Patch #1 fix checksum calculation in nfnetlink_queue with SCTP, segment GSO packet since skb_zerocopy() does not support GSO_BY_FRAGS, from Antonio Ojea. Patch #2 extend nfnetlink_queue coverage to handle SCTP packets, from Antonio Ojea. Patch #3 uses consume_skb() instead of kfree_skb() in nfnetlink, from Donald Hunter. Patch #4 adds a dedicate commit list for sets to speed up intra-transaction lookups, from Florian Westphal. Patch #5 skips removal of element from abort path for the pipapo backend, ditching the shadow copy of this datastructure is sufficient. Patch #6 moves nf_ct_netns_get() out of nf_conncount_init() to let users of conncoiunt decide when to enable conntrack, this is needed by openvswitch, from Xin Long. Patch #7 pass context to all nft_parse_register_load() in preparation for the next patch. Patches #8 and #9 reject loads from uninitialized registers from control plane to remove register initialization from datapath. From Florian Westphal. * tag 'nf-next-24-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next: netfilter: nf_tables: don't initialize registers in nft_do_chain() netfilter: nf_tables: allow loads only when register is initialized netfilter: nf_tables: pass context structure to nft_parse_register_load netfilter: move nf_ct_netns_get out of nf_conncount_init netfilter: nf_tables: do not remove elements if set backend implements .abort netfilter: nf_tables: store new sets in dedicated list netfilter: nfnetlink: convert kfree_skb to consume_skb selftests: netfilter: nft_queue.sh: sctp coverage netfilter: nfnetlink_queue: unbreak SCTP traffic ==================== Link: https://patch.msgid.link/20240822221939.157858-1-pablo@netfilter.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
b2ede25b7e
@ -15,10 +15,8 @@ struct nf_conncount_list {
|
||||
unsigned int count; /* length of list */
|
||||
};
|
||||
|
||||
struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
|
||||
unsigned int keylen);
|
||||
void nf_conncount_destroy(struct net *net, unsigned int family,
|
||||
struct nf_conncount_data *data);
|
||||
struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int keylen);
|
||||
void nf_conncount_destroy(struct net *net, struct nf_conncount_data *data);
|
||||
|
||||
unsigned int nf_conncount_count(struct net *net,
|
||||
struct nf_conncount_data *data,
|
||||
|
@ -221,6 +221,7 @@ struct nft_ctx {
|
||||
u8 family;
|
||||
u8 level;
|
||||
bool report;
|
||||
DECLARE_BITMAP(reg_inited, NFT_REG32_NUM);
|
||||
};
|
||||
|
||||
enum nft_data_desc_flags {
|
||||
@ -254,7 +255,8 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
|
||||
int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest);
|
||||
int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg);
|
||||
|
||||
int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len);
|
||||
int nft_parse_register_load(const struct nft_ctx *ctx,
|
||||
const struct nlattr *attr, u8 *sreg, u32 len);
|
||||
int nft_parse_register_store(const struct nft_ctx *ctx,
|
||||
const struct nlattr *attr, u8 *dreg,
|
||||
const struct nft_data *data,
|
||||
@ -1674,6 +1676,7 @@ struct nft_trans_rule {
|
||||
|
||||
struct nft_trans_set {
|
||||
struct nft_trans_binding nft_trans_binding;
|
||||
struct list_head list_trans_newset;
|
||||
struct nft_set *set;
|
||||
u32 set_id;
|
||||
u32 gc_int;
|
||||
@ -1875,6 +1878,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
|
||||
struct nftables_pernet {
|
||||
struct list_head tables;
|
||||
struct list_head commit_list;
|
||||
struct list_head commit_set_list;
|
||||
struct list_head binding_list;
|
||||
struct list_head module_list;
|
||||
struct list_head notify_list;
|
||||
|
@ -142,7 +142,7 @@ static int nft_meta_bridge_set_init(const struct nft_ctx *ctx,
|
||||
}
|
||||
|
||||
priv->len = len;
|
||||
err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_META_SREG], &priv->sreg, len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -3387,6 +3387,7 @@ int skb_crc32c_csum_help(struct sk_buff *skb)
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(skb_crc32c_csum_help);
|
||||
|
||||
__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
|
||||
{
|
||||
|
@ -40,13 +40,13 @@ static int nft_dup_ipv4_init(const struct nft_ctx *ctx,
|
||||
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
|
||||
sizeof(struct in_addr));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_DUP_SREG_DEV])
|
||||
err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV],
|
||||
&priv->sreg_dev, sizeof(int));
|
||||
|
||||
return err;
|
||||
|
@ -38,13 +38,13 @@ static int nft_dup_ipv6_init(const struct nft_ctx *ctx,
|
||||
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
|
||||
sizeof(struct in6_addr));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_DUP_SREG_DEV])
|
||||
err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV],
|
||||
&priv->sreg_dev, sizeof(int));
|
||||
|
||||
return err;
|
||||
|
@ -522,11 +522,10 @@ unsigned int nf_conncount_count(struct net *net,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conncount_count);
|
||||
|
||||
struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
|
||||
unsigned int keylen)
|
||||
struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int keylen)
|
||||
{
|
||||
struct nf_conncount_data *data;
|
||||
int ret, i;
|
||||
int i;
|
||||
|
||||
if (keylen % sizeof(u32) ||
|
||||
keylen / sizeof(u32) > MAX_KEYLEN ||
|
||||
@ -539,12 +538,6 @@ struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family
|
||||
if (!data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = nf_ct_netns_get(net, family);
|
||||
if (ret < 0) {
|
||||
kfree(data);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(data->root); ++i)
|
||||
data->root[i] = RB_ROOT;
|
||||
|
||||
@ -581,13 +574,11 @@ static void destroy_tree(struct rb_root *r)
|
||||
}
|
||||
}
|
||||
|
||||
void nf_conncount_destroy(struct net *net, unsigned int family,
|
||||
struct nf_conncount_data *data)
|
||||
void nf_conncount_destroy(struct net *net, struct nf_conncount_data *data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
cancel_work_sync(&data->gc_work);
|
||||
nf_ct_netns_put(net, family);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(data->root); ++i)
|
||||
destroy_tree(&data->root[i]);
|
||||
|
@ -146,6 +146,8 @@ static void nft_ctx_init(struct nft_ctx *ctx,
|
||||
ctx->report = nlmsg_report(nlh);
|
||||
ctx->flags = nlh->nlmsg_flags;
|
||||
ctx->seq = nlh->nlmsg_seq;
|
||||
|
||||
bitmap_zero(ctx->reg_inited, NFT_REG32_NUM);
|
||||
}
|
||||
|
||||
static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
|
||||
@ -393,6 +395,7 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(net);
|
||||
struct nft_trans_binding *binding;
|
||||
struct nft_trans_set *trans_set;
|
||||
|
||||
list_add_tail(&trans->list, &nft_net->commit_list);
|
||||
|
||||
@ -402,9 +405,13 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
|
||||
|
||||
switch (trans->msg_type) {
|
||||
case NFT_MSG_NEWSET:
|
||||
trans_set = nft_trans_container_set(trans);
|
||||
|
||||
if (!nft_trans_set_update(trans) &&
|
||||
nft_set_is_anonymous(nft_trans_set(trans)))
|
||||
list_add_tail(&binding->binding_list, &nft_net->binding_list);
|
||||
|
||||
list_add_tail(&trans_set->list_trans_newset, &nft_net->commit_set_list);
|
||||
break;
|
||||
case NFT_MSG_NEWCHAIN:
|
||||
if (!nft_trans_chain_update(trans) &&
|
||||
@ -611,6 +618,7 @@ static int __nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
|
||||
|
||||
trans_set = nft_trans_container_set(trans);
|
||||
INIT_LIST_HEAD(&trans_set->nft_trans_binding.binding_list);
|
||||
INIT_LIST_HEAD(&trans_set->list_trans_newset);
|
||||
|
||||
if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] && !desc) {
|
||||
nft_trans_set_id(trans) =
|
||||
@ -4485,17 +4493,16 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net,
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(net);
|
||||
u32 id = ntohl(nla_get_be32(nla));
|
||||
struct nft_trans *trans;
|
||||
struct nft_trans_set *trans;
|
||||
|
||||
list_for_each_entry(trans, &nft_net->commit_list, list) {
|
||||
if (trans->msg_type == NFT_MSG_NEWSET) {
|
||||
struct nft_set *set = nft_trans_set(trans);
|
||||
/* its likely the id we need is at the tail, not at start */
|
||||
list_for_each_entry_reverse(trans, &nft_net->commit_set_list, list_trans_newset) {
|
||||
struct nft_set *set = trans->set;
|
||||
|
||||
if (id == nft_trans_set_id(trans) &&
|
||||
set->table == table &&
|
||||
nft_active_genmask(set, genmask))
|
||||
return set;
|
||||
}
|
||||
if (id == trans->set_id &&
|
||||
set->table == table &&
|
||||
nft_active_genmask(set, genmask))
|
||||
return set;
|
||||
}
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
@ -10447,6 +10454,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
||||
nft_flow_rule_destroy(nft_trans_flow_rule(trans));
|
||||
break;
|
||||
case NFT_MSG_NEWSET:
|
||||
list_del(&nft_trans_container_set(trans)->list_trans_newset);
|
||||
if (nft_trans_set_update(trans)) {
|
||||
struct nft_set *set = nft_trans_set(trans);
|
||||
|
||||
@ -10755,6 +10763,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
case NFT_MSG_NEWSET:
|
||||
list_del(&nft_trans_container_set(trans)->list_trans_newset);
|
||||
if (nft_trans_set_update(trans)) {
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
@ -10782,7 +10791,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
||||
break;
|
||||
}
|
||||
te = nft_trans_container_elem(trans);
|
||||
nft_setelem_remove(net, te->set, te->elem_priv);
|
||||
if (!te->set->ops->abort ||
|
||||
nft_setelem_is_catchall(te->set, te->elem_priv))
|
||||
nft_setelem_remove(net, te->set, te->elem_priv);
|
||||
|
||||
if (!nft_setelem_is_catchall(te->set, te->elem_priv))
|
||||
atomic_dec(&te->set->nelems);
|
||||
|
||||
@ -10850,6 +10862,8 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(!list_empty(&nft_net->commit_set_list));
|
||||
|
||||
nft_set_abort_update(&set_update_list);
|
||||
|
||||
synchronize_rcu();
|
||||
@ -11026,10 +11040,11 @@ static int nft_validate_register_load(enum nft_registers reg, unsigned int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
|
||||
int nft_parse_register_load(const struct nft_ctx *ctx,
|
||||
const struct nlattr *attr, u8 *sreg, u32 len)
|
||||
{
|
||||
u32 reg;
|
||||
int err;
|
||||
int err, invalid_reg;
|
||||
u32 reg, next_register;
|
||||
|
||||
err = nft_parse_register(attr, ®);
|
||||
if (err < 0)
|
||||
@ -11039,11 +11054,36 @@ int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
next_register = DIV_ROUND_UP(len, NFT_REG32_SIZE) + reg;
|
||||
|
||||
/* Can't happen: nft_validate_register_load() should have failed */
|
||||
if (WARN_ON_ONCE(next_register > NFT_REG32_NUM))
|
||||
return -EINVAL;
|
||||
|
||||
/* find first register that did not see an earlier store. */
|
||||
invalid_reg = find_next_zero_bit(ctx->reg_inited, NFT_REG32_NUM, reg);
|
||||
|
||||
/* invalid register within the range that we're loading from? */
|
||||
if (invalid_reg < next_register)
|
||||
return -ENODATA;
|
||||
|
||||
*sreg = reg;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_parse_register_load);
|
||||
|
||||
static void nft_saw_register_store(const struct nft_ctx *__ctx,
|
||||
int reg, unsigned int len)
|
||||
{
|
||||
unsigned int registers = DIV_ROUND_UP(len, NFT_REG32_SIZE);
|
||||
struct nft_ctx *ctx = (struct nft_ctx *)__ctx;
|
||||
|
||||
if (WARN_ON_ONCE(len == 0 || reg < 0))
|
||||
return;
|
||||
|
||||
bitmap_set(ctx->reg_inited, reg, registers);
|
||||
}
|
||||
|
||||
static int nft_validate_register_store(const struct nft_ctx *ctx,
|
||||
enum nft_registers reg,
|
||||
const struct nft_data *data,
|
||||
@ -11065,7 +11105,7 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
if (type != NFT_DATA_VALUE)
|
||||
return -EINVAL;
|
||||
@ -11078,8 +11118,11 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
|
||||
sizeof_field(struct nft_regs, data))
|
||||
return -ERANGE;
|
||||
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
nft_saw_register_store(ctx, reg, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nft_parse_register_store(const struct nft_ctx *ctx,
|
||||
@ -11519,6 +11562,7 @@ static int __net_init nf_tables_init_net(struct net *net)
|
||||
|
||||
INIT_LIST_HEAD(&nft_net->tables);
|
||||
INIT_LIST_HEAD(&nft_net->commit_list);
|
||||
INIT_LIST_HEAD(&nft_net->commit_set_list);
|
||||
INIT_LIST_HEAD(&nft_net->binding_list);
|
||||
INIT_LIST_HEAD(&nft_net->module_list);
|
||||
INIT_LIST_HEAD(&nft_net->notify_list);
|
||||
@ -11549,6 +11593,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)
|
||||
gc_seq = nft_gc_seq_begin(nft_net);
|
||||
|
||||
WARN_ON_ONCE(!list_empty(&nft_net->commit_list));
|
||||
WARN_ON_ONCE(!list_empty(&nft_net->commit_set_list));
|
||||
|
||||
if (!list_empty(&nft_net->module_list))
|
||||
nf_tables_module_autoload_cleanup(net);
|
||||
|
@ -256,7 +256,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
|
||||
const struct net *net = nft_net(pkt);
|
||||
const struct nft_expr *expr, *last;
|
||||
const struct nft_rule_dp *rule;
|
||||
struct nft_regs regs = {};
|
||||
struct nft_regs regs;
|
||||
unsigned int stackptr = 0;
|
||||
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
|
||||
bool genbit = READ_ONCE(net->nft.gencursor);
|
||||
|
@ -402,27 +402,27 @@ replay_abort:
|
||||
{
|
||||
nfnl_unlock(subsys_id);
|
||||
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
|
||||
return kfree_skb(skb);
|
||||
return consume_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ss->valid_genid || !ss->commit || !ss->abort) {
|
||||
nfnl_unlock(subsys_id);
|
||||
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
|
||||
return kfree_skb(skb);
|
||||
return consume_skb(skb);
|
||||
}
|
||||
|
||||
if (!try_module_get(ss->owner)) {
|
||||
nfnl_unlock(subsys_id);
|
||||
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
|
||||
return kfree_skb(skb);
|
||||
return consume_skb(skb);
|
||||
}
|
||||
|
||||
if (!ss->valid_genid(net, genid)) {
|
||||
module_put(ss->owner);
|
||||
nfnl_unlock(subsys_id);
|
||||
netlink_ack(oskb, nlh, -ERESTART, NULL);
|
||||
return kfree_skb(skb);
|
||||
return consume_skb(skb);
|
||||
}
|
||||
|
||||
nfnl_unlock(subsys_id);
|
||||
@ -567,7 +567,7 @@ done:
|
||||
if (status & NFNL_BATCH_REPLAY) {
|
||||
ss->abort(net, oskb, NFNL_ABORT_AUTOLOAD);
|
||||
nfnl_err_reset(&err_list);
|
||||
kfree_skb(skb);
|
||||
consume_skb(skb);
|
||||
module_put(ss->owner);
|
||||
goto replay;
|
||||
} else if (status == NFNL_BATCH_DONE) {
|
||||
@ -593,7 +593,7 @@ done:
|
||||
err = ss->abort(net, oskb, abort_action);
|
||||
if (err == -EAGAIN) {
|
||||
nfnl_err_reset(&err_list);
|
||||
kfree_skb(skb);
|
||||
consume_skb(skb);
|
||||
module_put(ss->owner);
|
||||
status |= NFNL_BATCH_FAILURE;
|
||||
goto replay_abort;
|
||||
@ -601,7 +601,7 @@ done:
|
||||
}
|
||||
|
||||
nfnl_err_deliver(&err_list, oskb);
|
||||
kfree_skb(skb);
|
||||
consume_skb(skb);
|
||||
module_put(ss->owner);
|
||||
}
|
||||
|
||||
|
@ -540,6 +540,14 @@ nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int nf_queue_checksum_help(struct sk_buff *entskb)
|
||||
{
|
||||
if (skb_csum_is_sctp(entskb))
|
||||
return skb_crc32c_csum_help(entskb);
|
||||
|
||||
return skb_checksum_help(entskb);
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
struct nf_queue_entry *entry,
|
||||
@ -602,7 +610,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
case NFQNL_COPY_PACKET:
|
||||
if (!(queue->flags & NFQA_CFG_F_GSO) &&
|
||||
entskb->ip_summed == CHECKSUM_PARTIAL &&
|
||||
skb_checksum_help(entskb))
|
||||
nf_queue_checksum_help(entskb))
|
||||
return NULL;
|
||||
|
||||
data_len = READ_ONCE(queue->copy_range);
|
||||
@ -1014,7 +1022,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(skb))
|
||||
if (!skb_is_gso(skb) || ((queue->flags & NFQA_CFG_F_GSO) && !skb_is_gso_sctp(skb)))
|
||||
return __nfqnl_enqueue_packet(net, queue, entry);
|
||||
|
||||
nf_bridge_adjust_skb_data(skb);
|
||||
|
@ -171,7 +171,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
|
||||
|
||||
priv->len = len;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_BITWISE_SREG], &priv->sreg,
|
||||
priv->len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -365,7 +365,7 @@ static int nft_bitwise_fast_init(const struct nft_ctx *ctx,
|
||||
struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr);
|
||||
int err;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_BITWISE_SREG], &priv->sreg,
|
||||
sizeof(u32));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -139,7 +139,7 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
|
||||
|
||||
priv->len = len;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_BYTEORDER_SREG], &priv->sreg,
|
||||
priv->len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -83,7 +83,7 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -222,7 +222,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -323,7 +323,7 @@ static int nft_cmp16_fast_init(const struct nft_ctx *ctx,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -606,7 +606,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
|
||||
}
|
||||
|
||||
priv->len = len;
|
||||
err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len);
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_CT_SREG], &priv->sreg, len);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
|
||||
|
@ -40,7 +40,7 @@ static int nft_dup_netdev_init(const struct nft_ctx *ctx,
|
||||
if (tb[NFTA_DUP_SREG_DEV] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
return nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev,
|
||||
return nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev,
|
||||
sizeof(int));
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
|
||||
return err;
|
||||
}
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key,
|
||||
set->klen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -226,7 +226,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
|
||||
if (set->dtype == NFT_DATA_VERDICT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_DATA],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_DYNSET_SREG_DATA],
|
||||
&priv->sreg_data, set->dlen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -588,7 +588,7 @@ static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx,
|
||||
priv->flags = flags;
|
||||
priv->op = op;
|
||||
|
||||
return nft_parse_register_load(tb[NFTA_EXTHDR_SREG], &priv->sreg,
|
||||
return nft_parse_register_load(ctx, tb[NFTA_EXTHDR_SREG], &priv->sreg,
|
||||
priv->len);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ static int nft_fwd_netdev_init(const struct nft_ctx *ctx,
|
||||
if (tb[NFTA_FWD_SREG_DEV] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
return nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
|
||||
return nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
|
||||
sizeof(int));
|
||||
}
|
||||
|
||||
@ -178,12 +178,12 @@ static int nft_fwd_neigh_init(const struct nft_ctx *ctx,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
|
||||
sizeof(int));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return nft_parse_register_load(tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr,
|
||||
return nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr,
|
||||
addr_len);
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
|
||||
|
||||
priv->len = len;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_HASH_SREG], &priv->sreg, len);
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_HASH_SREG], &priv->sreg, len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -113,7 +113,7 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_LOOKUP_SREG], &priv->sreg,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_LOOKUP_SREG], &priv->sreg,
|
||||
set->klen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -52,13 +52,13 @@ static int nft_masq_init(const struct nft_ctx *ctx,
|
||||
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
|
||||
|
||||
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
|
||||
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_MASQ_REG_PROTO_MIN],
|
||||
&priv->sreg_proto_min, plen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_MASQ_REG_PROTO_MAX]) {
|
||||
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MAX],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_MASQ_REG_PROTO_MAX],
|
||||
&priv->sreg_proto_max,
|
||||
plen);
|
||||
if (err < 0)
|
||||
|
@ -657,7 +657,7 @@ int nft_meta_set_init(const struct nft_ctx *ctx,
|
||||
}
|
||||
|
||||
priv->len = len;
|
||||
err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_META_SREG], &priv->sreg, len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -214,13 +214,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
priv->family = family;
|
||||
|
||||
if (tb[NFTA_NAT_REG_ADDR_MIN]) {
|
||||
err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MIN],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_ADDR_MIN],
|
||||
&priv->sreg_addr_min, alen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_NAT_REG_ADDR_MAX]) {
|
||||
err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MAX],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_ADDR_MAX],
|
||||
&priv->sreg_addr_max,
|
||||
alen);
|
||||
if (err < 0)
|
||||
@ -234,13 +234,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
|
||||
plen = sizeof_field(struct nf_nat_range, min_proto.all);
|
||||
if (tb[NFTA_NAT_REG_PROTO_MIN]) {
|
||||
err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_PROTO_MIN],
|
||||
&priv->sreg_proto_min, plen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_NAT_REG_PROTO_MAX]) {
|
||||
err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MAX],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_PROTO_MAX],
|
||||
&priv->sreg_proto_max,
|
||||
plen);
|
||||
if (err < 0)
|
||||
|
@ -143,7 +143,7 @@ static int nft_objref_map_init(const struct nft_ctx *ctx,
|
||||
if (!(set->flags & NFT_SET_OBJECT))
|
||||
return -EINVAL;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_OBJREF_SET_SREG], &priv->sreg,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_OBJREF_SET_SREG], &priv->sreg,
|
||||
set->klen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -981,7 +981,7 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
|
||||
}
|
||||
priv->csum_type = csum_type;
|
||||
|
||||
return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg,
|
||||
return nft_parse_register_load(ctx, tb[NFTA_PAYLOAD_SREG], &priv->sreg,
|
||||
priv->len);
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ static int nft_queue_sreg_init(const struct nft_ctx *ctx,
|
||||
struct nft_queue *priv = nft_expr_priv(expr);
|
||||
int err;
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_QUEUE_SREG_QNUM],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_QUEUE_SREG_QNUM],
|
||||
&priv->sreg_qnum, sizeof(u32));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -83,7 +83,7 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
|
||||
goto err2;
|
||||
}
|
||||
|
||||
err = nft_parse_register_load(tb[NFTA_RANGE_SREG], &priv->sreg,
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_RANGE_SREG], &priv->sreg,
|
||||
desc_from.len);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
@ -51,13 +51,13 @@ static int nft_redir_init(const struct nft_ctx *ctx,
|
||||
|
||||
plen = sizeof_field(struct nf_nat_range, min_proto.all);
|
||||
if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
|
||||
err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_REDIR_REG_PROTO_MIN],
|
||||
&priv->sreg_proto_min, plen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_REDIR_REG_PROTO_MAX]) {
|
||||
err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MAX],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_REDIR_REG_PROTO_MAX],
|
||||
&priv->sreg_proto_max,
|
||||
plen);
|
||||
if (err < 0)
|
||||
|
@ -254,14 +254,14 @@ static int nft_tproxy_init(const struct nft_ctx *ctx,
|
||||
}
|
||||
|
||||
if (tb[NFTA_TPROXY_REG_ADDR]) {
|
||||
err = nft_parse_register_load(tb[NFTA_TPROXY_REG_ADDR],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_TPROXY_REG_ADDR],
|
||||
&priv->sreg_addr, alen);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (tb[NFTA_TPROXY_REG_PORT]) {
|
||||
err = nft_parse_register_load(tb[NFTA_TPROXY_REG_PORT],
|
||||
err = nft_parse_register_load(ctx, tb[NFTA_TPROXY_REG_PORT],
|
||||
&priv->sreg_port, sizeof(u16));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -86,6 +86,7 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_connlimit_info *info = par->matchinfo;
|
||||
unsigned int keylen;
|
||||
int ret;
|
||||
|
||||
keylen = sizeof(u32);
|
||||
if (par->family == NFPROTO_IPV6)
|
||||
@ -93,8 +94,17 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
|
||||
else
|
||||
keylen += sizeof(struct in_addr);
|
||||
|
||||
ret = nf_ct_netns_get(par->net, par->family);
|
||||
if (ret < 0) {
|
||||
pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
|
||||
par->family);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* init private data */
|
||||
info->data = nf_conncount_init(par->net, par->family, keylen);
|
||||
info->data = nf_conncount_init(par->net, keylen);
|
||||
if (IS_ERR(info->data))
|
||||
nf_ct_netns_put(par->net, par->family);
|
||||
|
||||
return PTR_ERR_OR_ZERO(info->data);
|
||||
}
|
||||
@ -103,7 +113,8 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
const struct xt_connlimit_info *info = par->matchinfo;
|
||||
|
||||
nf_conncount_destroy(par->net, par->family, info->data);
|
||||
nf_conncount_destroy(par->net, info->data);
|
||||
nf_ct_netns_put(par->net, par->family);
|
||||
}
|
||||
|
||||
static struct xt_match connlimit_mt_reg __read_mostly = {
|
||||
|
@ -1608,8 +1608,7 @@ static int ovs_ct_limit_init(struct net *net, struct ovs_net *ovs_net)
|
||||
for (i = 0; i < CT_LIMIT_HASH_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&ovs_net->ct_limit_info->limits[i]);
|
||||
|
||||
ovs_net->ct_limit_info->data =
|
||||
nf_conncount_init(net, NFPROTO_INET, sizeof(u32));
|
||||
ovs_net->ct_limit_info->data = nf_conncount_init(net, sizeof(u32));
|
||||
|
||||
if (IS_ERR(ovs_net->ct_limit_info->data)) {
|
||||
err = PTR_ERR(ovs_net->ct_limit_info->data);
|
||||
@ -1626,7 +1625,7 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
|
||||
const struct ovs_ct_limit_info *info = ovs_net->ct_limit_info;
|
||||
int i;
|
||||
|
||||
nf_conncount_destroy(net, NFPROTO_INET, info->data);
|
||||
nf_conncount_destroy(net, info->data);
|
||||
for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
|
||||
struct hlist_head *head = &info->limits[i];
|
||||
struct ovs_ct_limit *ct_limit;
|
||||
|
@ -87,3 +87,5 @@ CONFIG_XFRM_USER=m
|
||||
CONFIG_XFRM_STATISTICS=y
|
||||
CONFIG_NET_PKTGEN=m
|
||||
CONFIG_TUN=m
|
||||
CONFIG_INET_DIAG=m
|
||||
CONFIG_SCTP_DIAG=m
|
||||
|
@ -25,6 +25,9 @@ cleanup()
|
||||
}
|
||||
|
||||
checktool "nft --version" "test without nft tool"
|
||||
checktool "socat -h" "run test without socat"
|
||||
|
||||
modprobe -q sctp
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
@ -265,7 +268,6 @@ test_tcp_forward()
|
||||
|
||||
test_tcp_localhost()
|
||||
{
|
||||
dd conv=sparse status=none if=/dev/zero bs=1M count=200 of="$TMPINPUT"
|
||||
timeout 5 ip netns exec "$nsrouter" socat -u TCP-LISTEN:12345 STDOUT >/dev/null &
|
||||
local rpid=$!
|
||||
|
||||
@ -375,6 +377,82 @@ EOF
|
||||
wait 2>/dev/null
|
||||
}
|
||||
|
||||
sctp_listener_ready()
|
||||
{
|
||||
ss -S -N "$1" -ln -o "sport = :12345" | grep -q 12345
|
||||
}
|
||||
|
||||
test_sctp_forward()
|
||||
{
|
||||
ip netns exec "$nsrouter" nft -f /dev/stdin <<EOF
|
||||
flush ruleset
|
||||
table inet sctpq {
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy accept;
|
||||
sctp dport 12345 queue num 10
|
||||
}
|
||||
}
|
||||
EOF
|
||||
timeout 60 ip netns exec "$ns2" socat -u SCTP-LISTEN:12345 STDOUT > "$TMPFILE1" &
|
||||
local rpid=$!
|
||||
|
||||
busywait "$BUSYWAIT_TIMEOUT" sctp_listener_ready "$ns2"
|
||||
|
||||
ip netns exec "$nsrouter" ./nf_queue -q 10 -G -t "$timeout" &
|
||||
local nfqpid=$!
|
||||
|
||||
ip netns exec "$ns1" socat -u STDIN SCTP:10.0.2.99:12345 <"$TMPINPUT" >/dev/null
|
||||
|
||||
if ! ip netns exec "$nsrouter" nft delete table inet sctpq; then
|
||||
echo "FAIL: Could not delete sctpq table"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wait "$rpid" && echo "PASS: sctp and nfqueue in forward chain"
|
||||
|
||||
if ! diff -u "$TMPINPUT" "$TMPFILE1" ; then
|
||||
echo "FAIL: lost packets?!" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_sctp_output()
|
||||
{
|
||||
ip netns exec "$ns1" nft -f /dev/stdin <<EOF
|
||||
table inet sctpq {
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
sctp dport 12345 queue num 11
|
||||
}
|
||||
}
|
||||
EOF
|
||||
# reduce test file size, software segmentation causes sk wmem increase.
|
||||
dd conv=sparse status=none if=/dev/zero bs=1M count=50 of="$TMPINPUT"
|
||||
|
||||
timeout 60 ip netns exec "$ns2" socat -u SCTP-LISTEN:12345 STDOUT > "$TMPFILE1" &
|
||||
local rpid=$!
|
||||
|
||||
busywait "$BUSYWAIT_TIMEOUT" sctp_listener_ready "$ns2"
|
||||
|
||||
ip netns exec "$ns1" ./nf_queue -q 11 -t "$timeout" &
|
||||
local nfqpid=$!
|
||||
|
||||
ip netns exec "$ns1" socat -u STDIN SCTP:10.0.2.99:12345 <"$TMPINPUT" >/dev/null
|
||||
|
||||
if ! ip netns exec "$ns1" nft delete table inet sctpq; then
|
||||
echo "FAIL: Could not delete sctpq table"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# must wait before checking completeness of output file.
|
||||
wait "$rpid" && echo "PASS: sctp and nfqueue in output chain with GSO"
|
||||
|
||||
if ! diff -u "$TMPINPUT" "$TMPFILE1" ; then
|
||||
echo "FAIL: lost packets?!" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_queue_removal()
|
||||
{
|
||||
read tainted_then < /proc/sys/kernel/tainted
|
||||
@ -443,11 +521,16 @@ test_queue 10
|
||||
# same. We queue to a second program as well.
|
||||
load_ruleset "filter2" 20
|
||||
test_queue 20
|
||||
ip netns exec "$ns1" nft flush ruleset
|
||||
|
||||
test_tcp_forward
|
||||
test_tcp_localhost
|
||||
test_tcp_localhost_connectclose
|
||||
test_tcp_localhost_requeue
|
||||
test_sctp_forward
|
||||
test_sctp_output
|
||||
|
||||
# should be last, adds vrf device in ns1 and changes routes
|
||||
test_icmp_vrf
|
||||
test_queue_removal
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user