summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/ipv4/ip_fragment.c60
-rw-r--r--net/ipv4/route.c4
3 files changed, 41 insertions, 25 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 381813eae46c..1b122177c8fa 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -964,7 +964,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue,
} else
pos = map_len = alloc_len = 0;
- need_set = cpu_isset(cpu, *mask) && cpu_online(cpu);
+ need_set = cpumask_test_cpu(cpu, mask) && cpu_online(cpu);
#ifdef CONFIG_NUMA
if (need_set) {
if (numa_node == -2)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index b1d282f11be7..9e1458d3e465 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -77,22 +77,42 @@ struct ipq {
struct inet_peer *peer;
};
-#define IPFRAG_ECN_CLEAR 0x01 /* one frag had INET_ECN_NOT_ECT */
-#define IPFRAG_ECN_SET_CE 0x04 /* one frag had INET_ECN_CE */
+/* RFC 3168 support :
+ * We want to check ECN values of all fragments, do detect invalid combinations.
+ * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
+ */
+enum {
+ IPFRAG_ECN_NOT_ECT = 0x01, /* one frag had ECN_NOT_ECT */
+ IPFRAG_ECN_ECT_1 = 0x02, /* one frag had ECN_ECT_1 */
+ IPFRAG_ECN_ECT_0 = 0x04, /* one frag had ECN_ECT_0 */
+ IPFRAG_ECN_CE = 0x08, /* one frag had ECN_CE */
+};
static inline u8 ip4_frag_ecn(u8 tos)
{
- tos = (tos & INET_ECN_MASK) + 1;
- /*
- * After the last operation we have (in binary):
- * INET_ECN_NOT_ECT => 001
- * INET_ECN_ECT_1 => 010
- * INET_ECN_ECT_0 => 011
- * INET_ECN_CE => 100
- */
- return (tos & 2) ? 0 : tos;
+ return 1 << (tos & INET_ECN_MASK);
}
+/* Given the OR values of all fragments, apply RFC 3168 5.3 requirements
+ * Value : 0xff if frame should be dropped.
+ * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field
+ */
+static const u8 ip4_frag_ecn_table[16] = {
+ /* at least one fragment had CE, and others ECT_0 or ECT_1 */
+ [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = INET_ECN_CE,
+ [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = INET_ECN_CE,
+ [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = INET_ECN_CE,
+
+ /* invalid combinations : drop frame */
+ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE] = 0xff,
+ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0] = 0xff,
+ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_1] = 0xff,
+ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff,
+ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = 0xff,
+ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = 0xff,
+ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff,
+};
+
static struct inet_frags ip4_frags;
int ip_frag_nqueues(struct net *net)
@@ -524,9 +544,15 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
int len;
int ihlen;
int err;
+ u8 ecn;
ipq_kill(qp);
+ ecn = ip4_frag_ecn_table[qp->ecn];
+ if (unlikely(ecn == 0xff)) {
+ err = -EINVAL;
+ goto out_fail;
+ }
/* Make the one we just received the head. */
if (prev) {
head = prev->next;
@@ -605,17 +631,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
iph = ip_hdr(head);
iph->frag_off = 0;
iph->tot_len = htons(len);
- /* RFC3168 5.3 Fragmentation support
- * If one fragment had INET_ECN_NOT_ECT,
- * reassembled frame also has INET_ECN_NOT_ECT
- * Elif one fragment had INET_ECN_CE
- * reassembled frame also has INET_ECN_CE
- */
- if (qp->ecn & IPFRAG_ECN_CLEAR)
- iph->tos &= ~INET_ECN_MASK;
- else if (qp->ecn & IPFRAG_ECN_SET_CE)
- iph->tos |= INET_ECN_CE;
-
+ iph->tos |= ecn;
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
qp->q.fragments = NULL;
qp->q.fragments_tail = NULL;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index ad141d894e4e..cb93c32027d7 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1435,7 +1435,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
peer->rate_tokens == ip_rt_redirect_number &&
net_ratelimit())
printk(KERN_WARNING "host %pI4/if%d ignores redirects for %pI4 to %pI4.\n",
- &rt->rt_src, rt->rt_iif,
+ &ip_hdr(skb)->saddr, rt->rt_iif,
&rt->rt_dst, &rt->rt_gateway);
#endif
}
@@ -1704,7 +1704,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
__be32 src;
if (rt_is_output_route(rt))
- src = rt->rt_src;
+ src = ip_hdr(skb)->saddr;
else {
struct fib_result res;
struct flowi4 fl4;