aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/act_csum.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 945fb34ae721..c79aca29505e 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -559,8 +559,11 @@ static int tcf_csum_act(struct sk_buff *skb, const struct tc_action *a,
559 struct tcf_result *res) 559 struct tcf_result *res)
560{ 560{
561 struct tcf_csum *p = to_tcf_csum(a); 561 struct tcf_csum *p = to_tcf_csum(a);
562 bool orig_vlan_tag_present = false;
563 unsigned int vlan_hdr_count = 0;
562 struct tcf_csum_params *params; 564 struct tcf_csum_params *params;
563 u32 update_flags; 565 u32 update_flags;
566 __be16 protocol;
564 int action; 567 int action;
565 568
566 params = rcu_dereference_bh(p->params); 569 params = rcu_dereference_bh(p->params);
@@ -573,7 +576,9 @@ static int tcf_csum_act(struct sk_buff *skb, const struct tc_action *a,
573 goto drop; 576 goto drop;
574 577
575 update_flags = params->update_flags; 578 update_flags = params->update_flags;
576 switch (tc_skb_protocol(skb)) { 579 protocol = tc_skb_protocol(skb);
580again:
581 switch (protocol) {
577 case cpu_to_be16(ETH_P_IP): 582 case cpu_to_be16(ETH_P_IP):
578 if (!tcf_csum_ipv4(skb, update_flags)) 583 if (!tcf_csum_ipv4(skb, update_flags))
579 goto drop; 584 goto drop;
@@ -582,13 +587,35 @@ static int tcf_csum_act(struct sk_buff *skb, const struct tc_action *a,
582 if (!tcf_csum_ipv6(skb, update_flags)) 587 if (!tcf_csum_ipv6(skb, update_flags))
583 goto drop; 588 goto drop;
584 break; 589 break;
590 case cpu_to_be16(ETH_P_8021AD): /* fall through */
591 case cpu_to_be16(ETH_P_8021Q):
592 if (skb_vlan_tag_present(skb) && !orig_vlan_tag_present) {
593 protocol = skb->protocol;
594 orig_vlan_tag_present = true;
595 } else {
596 struct vlan_hdr *vlan = (struct vlan_hdr *)skb->data;
597
598 protocol = vlan->h_vlan_encapsulated_proto;
599 skb_pull(skb, VLAN_HLEN);
600 skb_reset_network_header(skb);
601 vlan_hdr_count++;
602 }
603 goto again;
604 }
605
606out:
607 /* Restore the skb for the pulled VLAN tags */
608 while (vlan_hdr_count--) {
609 skb_push(skb, VLAN_HLEN);
610 skb_reset_network_header(skb);
585 } 611 }
586 612
587 return action; 613 return action;
588 614
589drop: 615drop:
590 qstats_drop_inc(this_cpu_ptr(p->common.cpu_qstats)); 616 qstats_drop_inc(this_cpu_ptr(p->common.cpu_qstats));
591 return TC_ACT_SHOT; 617 action = TC_ACT_SHOT;
618 goto out;
592} 619}
593 620
594static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind, 621static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind,