Jiri, that seems to work.. Thanks. Let's upstream this patch Michael
בתאריך יום ג׳, 13 בנוב׳ 2018 ב-12:13 מאת Jiri Pirko <j...@resnulli.us >: > Mon, Nov 12, 2018 at 09:22:03PM CET, michaels...@gmail.com wrote: > >Calling it from net_dev_init doesn't look clean. > >If you will see who is calling 'dev_add_offload' you will find out that > >there are couple of modules that doing that except of the 8021q. so either > >all modules should add offload from net_dev_init or stay with the current > >model where each module adds its offload. > > > >When adding a vlan interface using 'ip link add', the module 8021q is > >loaded. What is the flow that causing ip link to load this module? > >Why can't we do the same thing when a vlan interface is created from ovs? > > > >Jiri, > >Any other idea how we can solve this issue? > > Could you please test following patch? I will send it upstream once you > confirm it helps your case. Thanks! > > From: Jiri Pirko <j...@mellanox.com> > Subject: [patch net-next RFC] net: 8021q: move vlan offload registrations > into > vlan_core > > Currently, the vlan packet offloads are registered only upon 8021q module > load. However, even without this module loaded, the offloads could be > utilized, for example by openvswitch datapath. As reported by Michael, > that causes 2x to 5x performance improvement, depending on a testcase. > > So move the vlan offload registrations into vlan_core and make this > available even without 8021q module loaded. > > Reported-by: Michael Shteinbok <michaels...@gmail.com> > Signed-off-by: Jiri Pirko <j...@mellanox.com> > --- > net/8021q/vlan.c | 96 ----------------------------------------- > net/8021q/vlan_core.c | 99 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 99 insertions(+), 96 deletions(-) > > diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c > index 1b7a375c6616..aef1a977279c 100644 > --- a/net/8021q/vlan.c > +++ b/net/8021q/vlan.c > @@ -648,93 +648,6 @@ static int vlan_ioctl_handler(struct net *net, void > __user *arg) > return err; > } > > -static struct sk_buff *vlan_gro_receive(struct list_head *head, > - struct sk_buff *skb) > -{ > - const struct packet_offload *ptype; > - unsigned int hlen, off_vlan; > - struct sk_buff *pp = NULL; > - struct vlan_hdr *vhdr; > - struct sk_buff *p; > - __be16 type; > - int flush = 1; > - > - off_vlan = skb_gro_offset(skb); > - hlen = off_vlan + sizeof(*vhdr); > - vhdr = skb_gro_header_fast(skb, off_vlan); > - if (skb_gro_header_hard(skb, hlen)) { > - vhdr = skb_gro_header_slow(skb, hlen, off_vlan); > - if (unlikely(!vhdr)) > - goto out; > - } > - > - type = vhdr->h_vlan_encapsulated_proto; > - > - rcu_read_lock(); > - ptype = gro_find_receive_by_type(type); > - if (!ptype) > - goto out_unlock; > - > - flush = 0; > - > - list_for_each_entry(p, head, list) { > - struct vlan_hdr *vhdr2; > - > - if (!NAPI_GRO_CB(p)->same_flow) > - continue; > - > - vhdr2 = (struct vlan_hdr *)(p->data + off_vlan); > - if (compare_vlan_header(vhdr, vhdr2)) > - NAPI_GRO_CB(p)->same_flow = 0; > - } > - > - skb_gro_pull(skb, sizeof(*vhdr)); > - skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr)); > - pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); > - > -out_unlock: > - rcu_read_unlock(); > -out: > - skb_gro_flush_final(skb, pp, flush); > - > - return pp; > -} > - > -static int vlan_gro_complete(struct sk_buff *skb, int nhoff) > -{ > - struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data + nhoff); > - __be16 type = vhdr->h_vlan_encapsulated_proto; > - struct packet_offload *ptype; > - int err = -ENOENT; > - > - rcu_read_lock(); > - ptype = gro_find_complete_by_type(type); > - if (ptype) > - err = ptype->callbacks.gro_complete(skb, nhoff + > sizeof(*vhdr)); > - > - rcu_read_unlock(); > - return err; > -} > - > -static struct packet_offload vlan_packet_offloads[] __read_mostly = { > - { > - .type = cpu_to_be16(ETH_P_8021Q), > - .priority = 10, > - .callbacks = { > - .gro_receive = vlan_gro_receive, > - .gro_complete = vlan_gro_complete, > - }, > - }, > - { > - .type = cpu_to_be16(ETH_P_8021AD), > - .priority = 10, > - .callbacks = { > - .gro_receive = vlan_gro_receive, > - .gro_complete = vlan_gro_complete, > - }, > - }, > -}; > - > static int __net_init vlan_init_net(struct net *net) > { > struct vlan_net *vn = net_generic(net, vlan_net_id); > @@ -762,7 +675,6 @@ static struct pernet_operations vlan_net_ops = { > static int __init vlan_proto_init(void) > { > int err; > - unsigned int i; > > pr_info("%s v%s\n", vlan_fullname, vlan_version); > > @@ -786,9 +698,6 @@ static int __init vlan_proto_init(void) > if (err < 0) > goto err5; > > - for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++) > - dev_add_offload(&vlan_packet_offloads[i]); > - > vlan_ioctl_set(vlan_ioctl_handler); > return 0; > > @@ -806,13 +715,8 @@ static int __init vlan_proto_init(void) > > static void __exit vlan_cleanup_module(void) > { > - unsigned int i; > - > vlan_ioctl_set(NULL); > > - for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++) > - dev_remove_offload(&vlan_packet_offloads[i]); > - > vlan_netlink_fini(); > > unregister_netdevice_notifier(&vlan_notifier_block); > diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c > index 57425049faf2..a313165e7a67 100644 > --- a/net/8021q/vlan_core.c > +++ b/net/8021q/vlan_core.c > @@ -453,3 +453,102 @@ bool vlan_uses_dev(const struct net_device *dev) > return vlan_info->grp.nr_vlan_devs ? true : false; > } > EXPORT_SYMBOL(vlan_uses_dev); > + > +static struct sk_buff *vlan_gro_receive(struct list_head *head, > + struct sk_buff *skb) > +{ > + const struct packet_offload *ptype; > + unsigned int hlen, off_vlan; > + struct sk_buff *pp = NULL; > + struct vlan_hdr *vhdr; > + struct sk_buff *p; > + __be16 type; > + int flush = 1; > + > + off_vlan = skb_gro_offset(skb); > + hlen = off_vlan + sizeof(*vhdr); > + vhdr = skb_gro_header_fast(skb, off_vlan); > + if (skb_gro_header_hard(skb, hlen)) { > + vhdr = skb_gro_header_slow(skb, hlen, off_vlan); > + if (unlikely(!vhdr)) > + goto out; > + } > + > + type = vhdr->h_vlan_encapsulated_proto; > + > + rcu_read_lock(); > + ptype = gro_find_receive_by_type(type); > + if (!ptype) > + goto out_unlock; > + > + flush = 0; > + > + list_for_each_entry(p, head, list) { > + struct vlan_hdr *vhdr2; > + > + if (!NAPI_GRO_CB(p)->same_flow) > + continue; > + > + vhdr2 = (struct vlan_hdr *)(p->data + off_vlan); > + if (compare_vlan_header(vhdr, vhdr2)) > + NAPI_GRO_CB(p)->same_flow = 0; > + } > + > + skb_gro_pull(skb, sizeof(*vhdr)); > + skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr)); > + pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); > + > +out_unlock: > + rcu_read_unlock(); > +out: > + skb_gro_flush_final(skb, pp, flush); > + > + return pp; > +} > + > +static int vlan_gro_complete(struct sk_buff *skb, int nhoff) > +{ > + struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data + nhoff); > + __be16 type = vhdr->h_vlan_encapsulated_proto; > + struct packet_offload *ptype; > + int err = -ENOENT; > + > + rcu_read_lock(); > + ptype = gro_find_complete_by_type(type); > + if (ptype) > + err = ptype->callbacks.gro_complete(skb, nhoff + > sizeof(*vhdr)); > + > + rcu_read_unlock(); > + return err; > +} > + > +static struct packet_offload vlan_packet_offloads[] __read_mostly = { > + { > + .type = cpu_to_be16(ETH_P_8021Q), > + .priority = 10, > + .callbacks = { > + .gro_receive = vlan_gro_receive, > + .gro_complete = vlan_gro_complete, > + }, > + }, > + { > + .type = cpu_to_be16(ETH_P_8021AD), > + .priority = 10, > + .callbacks = { > + .gro_receive = vlan_gro_receive, > + .gro_complete = vlan_gro_complete, > + }, > + }, > +}; > + > +static int __init vlan_offload_init(void) > +{ > + unsigned int i; > + > + for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++) > + dev_add_offload(&vlan_packet_offloads[i]); > + > + return 0; > +} > + > +fs_initcall(vlan_offload_init); > -- > 2.17.0 > > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev