Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c435e2e authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

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: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 85f1e7c2
Loading
Loading
Loading
Loading
+12 −54
Original line number Original line Diff line number Diff line
@@ -73,6 +73,8 @@ void nf_conntrack_unregister_notifier(struct net *net,
				      struct nf_ct_event_notifier *nb);
				      struct nf_ct_event_notifier *nb);


void nf_ct_deliver_cached_events(struct nf_conn *ct);
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
static inline void
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
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);
	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
static inline int
nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
			  u32 portid, int report)
			  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);
	return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
}
}


static inline int
static inline int
nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
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);
	return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
}
}


+54 −0
Original line number Original line Diff line number Diff line
@@ -113,6 +113,60 @@ static void ecache_work(struct work_struct *work)
		schedule_delayed_work(&ctnet->ecache_dwork, delay);
		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
/* deliver cached events and clear cache entry - must be called with locally
 * disabled softirqs */
 * disabled softirqs */
void nf_ct_deliver_cached_events(struct nf_conn *ct)
void nf_ct_deliver_cached_events(struct nf_conn *ct)