Patch v4.4.100 to Cradlepoint Current
Change-Id: Ia3c8d927e2d4445cc67793de5468074e521507a3
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 1c4ad47..c79dec5 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -327,6 +327,12 @@
spin_unlock(&x->lock);
+ /* cradlepoint */
+ write_seqlock(&net->xfrm.xfrm_total_stats_lock);
+ net->xfrm.total_bytes += skb->len;
+ net->xfrm.total_packets++;
+ write_sequnlock(&net->xfrm.xfrm_total_stats_lock);
+
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
inner_mode = x->inner_mode;
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index ff4a91f..80718d9 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -97,6 +97,12 @@
spin_unlock_bh(&x->lock);
+ /* cradlepoint */
+ write_seqlock_bh(&net->xfrm.xfrm_total_stats_lock);
+ net->xfrm.total_bytes += skb->len;
+ net->xfrm.total_packets++;
+ write_sequnlock_bh(&net->xfrm.xfrm_total_stats_lock);
+
skb_dst_force(skb);
err = x->type->output(x, skb);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 0e01250..adbb453 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -117,6 +117,7 @@
static inline struct dst_entry *__xfrm_dst_lookup(struct net *net,
int tos, int oif,
+ int mark,
const xfrm_address_t *saddr,
const xfrm_address_t *daddr,
int family)
@@ -128,7 +129,7 @@
if (unlikely(afinfo == NULL))
return ERR_PTR(-EAFNOSUPPORT);
- dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr);
+ dst = afinfo->dst_lookup(net, tos, oif, mark, saddr, daddr);
xfrm_policy_put_afinfo(afinfo);
@@ -137,6 +138,7 @@
static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
int tos, int oif,
+ int mark,
xfrm_address_t *prev_saddr,
xfrm_address_t *prev_daddr,
int family)
@@ -155,7 +157,7 @@
daddr = x->coaddr;
}
- dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family);
+ dst = __xfrm_dst_lookup(net, tos, oif, mark, saddr, daddr, family);
if (!IS_ERR(dst)) {
if (prev_saddr != saddr)
@@ -1524,6 +1526,21 @@
return tos;
}
+static inline int xfrm_get_mark(const struct flowi *fl, int family)
+{
+ struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+ int mark;
+
+ if (!afinfo)
+ return -EINVAL;
+
+ mark = afinfo->get_mark(fl);
+
+ xfrm_policy_put_afinfo(afinfo);
+
+ return mark;
+}
+
static struct flow_cache_object *xfrm_bundle_flo_get(struct flow_cache_object *flo)
{
struct xfrm_dst *xdst = container_of(flo, struct xfrm_dst, flo);
@@ -1666,6 +1683,7 @@
int nfheader_len = 0;
int trailer_len = 0;
int tos;
+ int mark;
int family = policy->selector.family;
xfrm_address_t saddr, daddr;
@@ -1676,6 +1694,8 @@
if (tos < 0)
goto put_states;
+ mark = xfrm_get_mark(fl, family);
+
dst_hold(dst);
for (; i < nx; i++) {
@@ -1711,7 +1731,7 @@
if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
family = xfrm[i]->props.family;
- dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
+ dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif, mark,
&saddr, &daddr, family);
err = PTR_ERR(dst);
if (IS_ERR(dst))
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index 05a6e3d..9bc3217 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -9,9 +9,44 @@
net->xfrm.sysctl_aevent_rseqth = XFRM_AE_SEQT_SIZE;
net->xfrm.sysctl_larval_drop = 1;
net->xfrm.sysctl_acq_expires = 30;
+
+ // cradlepoint
+ net->xfrm.total_packets = 0;
+ net->xfrm.total_bytes = 0;
}
#ifdef CONFIG_SYSCTL
+
+// cradlepoint
+int proc_total_stats(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ u64 val;
+ int ret;
+ unsigned int seq;
+ seqlock_t *lock = &((struct net*)table->extra1)->xfrm.xfrm_total_stats_lock;
+
+ if (write)
+ return -EPERM;
+
+ do {
+ seq = read_seqbegin(lock);
+ val = *(u64 *)(table->extra2);
+ } while (read_seqretry(lock, seq));
+
+ table->data = kmalloc(table->maxlen, GFP_USER);
+ if (!table->data)
+ return -ENOMEM;
+
+ snprintf((char*)(table->data), table->maxlen, "%llu", val);
+
+ ret = proc_dostring(table, write, buffer, lenp, ppos);
+
+ kfree(table->data);
+
+ return ret;
+}
+
static struct ctl_table xfrm_table[] = {
{
.procname = "xfrm_aevent_etime",
@@ -37,6 +72,20 @@
.mode = 0644,
.proc_handler = proc_dointvec
},
+ {
+ /* cradlepoint */
+ .procname = "xfrm_total_packets",
+ .maxlen = 256,
+ .mode = 0644,
+ .proc_handler = proc_total_stats
+ },
+ {
+ /* cradlepoint */
+ .procname = "xfrm_total_bytes",
+ .maxlen = 256,
+ .mode = 0644,
+ .proc_handler = proc_total_stats
+ },
{}
};
@@ -54,6 +103,12 @@
table[2].data = &net->xfrm.sysctl_larval_drop;
table[3].data = &net->xfrm.sysctl_acq_expires;
+ // cradlepoint xfrm total counters
+ table[4].extra1 = (void*) net;
+ table[4].extra2 = &net->xfrm.total_packets;
+ table[5].extra1 = (void*) net;
+ table[5].extra2 = &net->xfrm.total_bytes;
+
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
table[0].procname = NULL;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 7a5a64e..bfcc7d8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -3132,6 +3132,10 @@
return -ENOMEM;
net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */
rcu_assign_pointer(net->xfrm.nlsk, nlsk);
+
+ /* cradlepoint */
+ seqlock_init(&net->xfrm.xfrm_total_stats_lock);
+
return 0;
}