Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Conflicts:
	net/ipv4/ip_gre.c

Minor conflicts between tunnel bug fixes in net and
ipv6 tunnel cleanups in net-next.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2016-05-04 00:52:29 -04:00
263개의 변경된 파일2440개의 추가작업 그리고 1224개의 파일을 삭제

파일 보기

@@ -395,6 +395,25 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
sch->q.qlen++;
}
/* netem can't properly corrupt a megapacket (like we get from GSO), so instead
* when we statistically choose to corrupt one, we instead segment it, returning
* the first packet to be corrupted, and re-enqueue the remaining frames
*/
static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch)
{
struct sk_buff *segs;
netdev_features_t features = netif_skb_features(skb);
segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
if (IS_ERR_OR_NULL(segs)) {
qdisc_reshape_fail(skb, sch);
return NULL;
}
consume_skb(skb);
return segs;
}
/*
* Insert one skb into qdisc.
* Note: parent depends on return value to account for queue length.
@@ -407,7 +426,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
/* We don't fill cb now as skb_unshare() may invalidate it */
struct netem_skb_cb *cb;
struct sk_buff *skb2;
struct sk_buff *segs = NULL;
unsigned int len = 0, last_len, prev_len = qdisc_pkt_len(skb);
int nb = 0;
int count = 1;
int rc = NET_XMIT_SUCCESS;
/* Random duplication */
if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
@@ -453,10 +476,23 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
* do it now in software before we mangle it.
*/
if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
if (skb_is_gso(skb)) {
segs = netem_segment(skb, sch);
if (!segs)
return NET_XMIT_DROP;
} else {
segs = skb;
}
skb = segs;
segs = segs->next;
if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
(skb->ip_summed == CHECKSUM_PARTIAL &&
skb_checksum_help(skb)))
return qdisc_drop(skb, sch);
skb_checksum_help(skb))) {
rc = qdisc_drop(skb, sch);
goto finish_segs;
}
skb->data[prandom_u32() % skb_headlen(skb)] ^=
1<<(prandom_u32() % 8);
@@ -516,6 +552,27 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
sch->qstats.requeues++;
}
finish_segs:
if (segs) {
while (segs) {
skb2 = segs->next;
segs->next = NULL;
qdisc_skb_cb(segs)->pkt_len = segs->len;
last_len = segs->len;
rc = qdisc_enqueue(segs, sch);
if (rc != NET_XMIT_SUCCESS) {
if (net_xmit_drop_count(rc))
qdisc_qstats_drop(sch);
} else {
nb++;
len += last_len;
}
segs = skb2;
}
sch->q.qlen += nb;
if (nb > 1)
qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
}
return NET_XMIT_SUCCESS;
}