From 15824ab29f364abd3299ecd17ea48473d971aa79 Mon Sep 17 00:00:00 2001 From: Stephane Bryant Date: Sat, 26 Mar 2016 08:42:11 +0100 Subject: netfilter: bridge: pass L2 header and VLAN as netlink attributes in queues to userspace - This creates 2 netlink attribute NFQA_VLAN and NFQA_L2HDR. - These are filled up for the PF_BRIDGE family on the way to userspace. - NFQA_VLAN is a nested attribute, with the NFQA_VLAN_PROTO and the NFQA_VLAN_TCI carrying the corresponding vlan_proto and vlan_tci fields from the skb using big endian ordering (and using the CFI bit as the VLAN_TAG_PRESENT flag in vlan_tci as in the skb) Signed-off-by: Stephane Bryant Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nfnetlink_queue.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include') diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h index b67a853638ff..ae30841ff94e 100644 --- a/include/uapi/linux/netfilter/nfnetlink_queue.h +++ b/include/uapi/linux/netfilter/nfnetlink_queue.h @@ -30,6 +30,14 @@ struct nfqnl_msg_packet_timestamp { __aligned_be64 usec; }; +enum nfqnl_vlan_attr { + NFQA_VLAN_UNSPEC, + NFQA_VLAN_PROTO, /* __be16 skb vlan_proto */ + NFQA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */ + __NFQA_VLAN_MAX, +}; +#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX + 1) + enum nfqnl_attr_type { NFQA_UNSPEC, NFQA_PACKET_HDR, @@ -50,6 +58,8 @@ enum nfqnl_attr_type { NFQA_UID, /* __u32 sk uid */ NFQA_GID, /* __u32 sk gid */ NFQA_SECCTX, /* security context string */ + NFQA_VLAN, /* nested attribute: packet vlan info */ + NFQA_L2HDR, /* full L2 header */ __NFQA_MAX }; -- cgit From 3c435e2e414e82ec6c0e96a1dfc2be3ddc3c23b4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Apr 2016 21:52:35 +0200 Subject: netfilter: conntrack: de-inline nf_conntrack_eventmask_report Way too large; move it to nf_conntrack_ecache.c. Reduces total object size by 1216 byte on my machine. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_ecache.h | 66 ++++++----------------------- net/netfilter/nf_conntrack_ecache.c | 54 +++++++++++++++++++++++ 2 files changed, 66 insertions(+), 54 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 57c880378443..019a5b859868 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -73,6 +73,8 @@ void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb); void nf_ct_deliver_cached_events(struct nf_conn *ct); +int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, + u32 portid, int report); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) @@ -90,70 +92,26 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) set_bit(event, &e->cache); } -static inline int -nf_conntrack_eventmask_report(unsigned int eventmask, - struct nf_conn *ct, - u32 portid, - int report) -{ - int ret = 0; - struct net *net = nf_ct_net(ct); - struct nf_ct_event_notifier *notify; - struct nf_conntrack_ecache *e; - - rcu_read_lock(); - notify = rcu_dereference(net->ct.nf_conntrack_event_cb); - if (notify == NULL) - goto out_unlock; - - e = nf_ct_ecache_find(ct); - if (e == NULL) - goto out_unlock; - - if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { - struct nf_ct_event item = { - .ct = ct, - .portid = e->portid ? e->portid : portid, - .report = report - }; - /* This is a resent of a destroy event? If so, skip missed */ - unsigned long missed = e->portid ? 0 : e->missed; - - if (!((eventmask | missed) & e->ctmask)) - goto out_unlock; - - ret = notify->fcn(eventmask | missed, &item); - if (unlikely(ret < 0 || missed)) { - spin_lock_bh(&ct->lock); - if (ret < 0) { - /* This is a destroy event that has been - * triggered by a process, we store the PORTID - * to include it in the retransmission. */ - if (eventmask & (1 << IPCT_DESTROY) && - e->portid == 0 && portid != 0) - e->portid = portid; - else - e->missed |= eventmask; - } else - e->missed &= ~missed; - spin_unlock_bh(&ct->lock); - } - } -out_unlock: - rcu_read_unlock(); - return ret; -} - static inline int nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, u32 portid, int report) { + const struct net *net = nf_ct_net(ct); + + if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) + return 0; + return nf_conntrack_eventmask_report(1 << event, ct, portid, report); } static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { + const struct net *net = nf_ct_net(ct); + + if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) + return 0; + return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); } diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 4e78c57b818f..a0ebab96a92f 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -113,6 +113,60 @@ static void ecache_work(struct work_struct *work) schedule_delayed_work(&ctnet->ecache_dwork, delay); } +int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, + u32 portid, int report) +{ + int ret = 0; + struct net *net = nf_ct_net(ct); + struct nf_ct_event_notifier *notify; + struct nf_conntrack_ecache *e; + + rcu_read_lock(); + notify = rcu_dereference(net->ct.nf_conntrack_event_cb); + if (!notify) + goto out_unlock; + + e = nf_ct_ecache_find(ct); + if (!e) + goto out_unlock; + + if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { + struct nf_ct_event item = { + .ct = ct, + .portid = e->portid ? e->portid : portid, + .report = report + }; + /* This is a resent of a destroy event? If so, skip missed */ + unsigned long missed = e->portid ? 0 : e->missed; + + if (!((eventmask | missed) & e->ctmask)) + goto out_unlock; + + ret = notify->fcn(eventmask | missed, &item); + if (unlikely(ret < 0 || missed)) { + spin_lock_bh(&ct->lock); + if (ret < 0) { + /* This is a destroy event that has been + * triggered by a process, we store the PORTID + * to include it in the retransmission. + */ + if (eventmask & (1 << IPCT_DESTROY) && + e->portid == 0 && portid != 0) + e->portid = portid; + else + e->missed |= eventmask; + } else { + e->missed &= ~missed; + } + spin_unlock_bh(&ct->lock); + } + } +out_unlock: + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL_GPL(nf_conntrack_eventmask_report); + /* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ void nf_ct_deliver_cached_events(struct nf_conn *ct) -- cgit From ecdfb48cddfd1096343148113d5b1bd789033aa8 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Apr 2016 21:52:36 +0200 Subject: netfilter: conntrack: move expectation event helper to ecache.c Not performance critical, it is only invoked when an expectation is added/destroyed. While at it, kill unused nf_ct_expect_event() wrapper. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_ecache.h | 42 +++-------------------------- net/netfilter/nf_conntrack_ecache.c | 30 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 39 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 019a5b859868..fa36447371c6 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -130,43 +130,9 @@ int nf_ct_expect_register_notifier(struct net *net, void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb); -static inline void -nf_ct_expect_event_report(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp, - u32 portid, - int report) -{ - struct net *net = nf_ct_exp_net(exp); - struct nf_exp_event_notifier *notify; - struct nf_conntrack_ecache *e; - - rcu_read_lock(); - notify = rcu_dereference(net->ct.nf_expect_event_cb); - if (notify == NULL) - goto out_unlock; - - e = nf_ct_ecache_find(exp->master); - if (e == NULL) - goto out_unlock; - - if (e->expmask & (1 << event)) { - struct nf_exp_event item = { - .exp = exp, - .portid = portid, - .report = report - }; - notify->fcn(1 << event, &item); - } -out_unlock: - rcu_read_unlock(); -} - -static inline void -nf_ct_expect_event(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp) -{ - nf_ct_expect_event_report(event, exp, 0, 0); -} +void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, + struct nf_conntrack_expect *exp, + u32 portid, int report); int nf_conntrack_ecache_pernet_init(struct net *net); void nf_conntrack_ecache_pernet_fini(struct net *net); @@ -203,8 +169,6 @@ static inline int nf_conntrack_event_report(enum ip_conntrack_events event, u32 portid, int report) { return 0; } static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} -static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, - struct nf_conntrack_expect *exp) {} static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, struct nf_conntrack_expect *exp, u32 portid, diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index a0ebab96a92f..d28011b42845 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -221,6 +221,36 @@ out_unlock: } EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); +void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, + struct nf_conntrack_expect *exp, + u32 portid, int report) + +{ + struct net *net = nf_ct_exp_net(exp); + struct nf_exp_event_notifier *notify; + struct nf_conntrack_ecache *e; + + rcu_read_lock(); + notify = rcu_dereference(net->ct.nf_expect_event_cb); + if (!notify) + goto out_unlock; + + e = nf_ct_ecache_find(exp->master); + if (!e) + goto out_unlock; + + if (e->expmask & (1 << event)) { + struct nf_exp_event item = { + .exp = exp, + .portid = portid, + .report = report + }; + notify->fcn(1 << event, &item); + } +out_unlock: + rcu_read_unlock(); +} + int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *new) { -- cgit