On Fri, 2019-05-31 at 11:38 -0700, Cong Wang wrote: > On Fri, May 31, 2019 at 10:26 AM Davide Caratti <dcara...@redhat.com> wrote: > > diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c > > index 14bb525e355e..e8308ddcae9d 100644 > > --- a/net/sched/act_csum.c > > +++ b/net/sched/act_csum.c > > @@ -574,7 +574,6 @@ static int tcf_csum_act(struct sk_buff *skb, const > > struct tc_action *a, > > struct tcf_result *res) > > { > > struct tcf_csum *p = to_tcf_csum(a); > > - bool orig_vlan_tag_present = false; > > unsigned int vlan_hdr_count = 0; > > struct tcf_csum_params *params; > > u32 update_flags; > > @@ -604,17 +603,8 @@ static int tcf_csum_act(struct sk_buff *skb, const > > struct tc_action *a, > > break; > > case cpu_to_be16(ETH_P_8021AD): /* fall through */ > > case cpu_to_be16(ETH_P_8021Q): > > - if (skb_vlan_tag_present(skb) && !orig_vlan_tag_present) { > > - protocol = skb->protocol; > > - orig_vlan_tag_present = true; > > - } else { > > - struct vlan_hdr *vlan = (struct vlan_hdr > > *)skb->data; > > - > > - protocol = vlan->h_vlan_encapsulated_proto; > > - skb_pull(skb, VLAN_HLEN); > > - skb_reset_network_header(skb); > > - vlan_hdr_count++; > > - } > > + if (tc_skb_pull_vlans(skb, &vlan_hdr_count, &protocol)) > > + goto drop; > > goto again;
Please note: this loop was here also before this patch (the 'goto again;' line is only patch context). It has been introduced with commit 2ecba2d1e45b ("net: sched: act_csum: Fix csum calc for tagged packets"). > Why do you still need to loop here? tc_skb_pull_vlans() already > contains a loop to pop all vlan tags? The reason why the loop is here is: 1) in case there is a stripped vlan tag, it replaces tc_skb_protocol(skb) with the inner ethertype (i.e. skb->protocol) 2) in case there is one or more unstripped VLAN tags, it pulls them. At the last iteration, when it does: goto again; 'protocol' contains the innermost ethertype, read from 'h_vlan_encapsulated_proto'. If that value is 0x0800 (IPv4) or 0x86dd (IPv6), 'act_csum' will go on computing the internet checksum for the IPv4 header or for (some of the) IPv6 'nexthdrs'. (yes, we could move the call to tc_skb_pull_vlans() before the switch statement to make this code more understandable, also in the other 2 actions. Please let me know if you think it's better). > > > } > > > > diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c > > index d4699156974a..382ee69fb1a5 100644 > > --- a/net/sched/cls_api.c > > +++ b/net/sched/cls_api.c > > @@ -3300,6 +3300,28 @@ unsigned int tcf_exts_num_actions(struct tcf_exts > > *exts) > > } > > EXPORT_SYMBOL(tcf_exts_num_actions); > > > > +int tc_skb_pull_vlans(struct sk_buff *skb, unsigned int *hdr_count, > > + __be16 *proto) > > It looks like this function fits better in net/core/skbuff.c, because > I don't see anything TC specific. Ok, I don't know if other parts of the kernel really need it. Its use should be combined with tc_skb_protocol(), which is in pkt_sched.h. But i can move it to skbuff, or elsewhwere, unless somebody disagrees. > > > +{ > > + if (skb_vlan_tag_present(skb)) > > + *proto = skb->protocol; > > + > > + while (eth_type_vlan(*proto)) { > > + struct vlan_hdr *vlan; > > + > > + if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) > > + return -ENOMEM; > > + > > + vlan = (struct vlan_hdr *)skb->data; > > + *proto = vlan->h_vlan_encapsulated_proto; > > + skb_pull(skb, VLAN_HLEN); > > + skb_reset_network_header(skb); Again, this code was in act_csum.c also before. The only intention of this patch is to ensure that pskb_may_pull() is called before skb_pull(), as per Eric suggestion, and move this code out of act_csum to use it with other TC actions. > Any reason not to call __skb_vlan_pop() directly? I think we can't use __skb_vlan_pop(), because 'act_csum' needs to read the innermost ethertype in the packet to understand if it's IPv4, IPv6 or else (ARP, EAPOL, ...). If I well read __skb_vlan_pop(), it returns the VLAN ID, which is useless here. > > > + (*hdr_count)++; > > + } > > + return 0; > > +} > > Thanks. Thanks for reviewing, looking forward to read more comments from you!