- /* GSO is not implemented for packets with an 802.1Q header, so
- * we have to do segmentation before we add that header.
- *
- * GSO does work with hardware-accelerated VLAN tagging, but we
- * can't use hardware-accelerated VLAN tagging since it
- * requires the device to have a VLAN group configured (with
- * e.g. vconfig(8)) and we don't do that.
- *
- * Having to do this here may be a performance loss, since we
- * can't take advantage of TSO hardware support, although it
- * does not make a measurable network performance difference
- * for 1G Ethernet. Fixing that would require patching the
- * kernel (either to add GSO support to the VLAN protocol or to
- * support hardware-accelerated VLAN tagging without VLAN
- * groups configured). */
- if (skb_is_gso(skb)) {
- const struct nlattr *actions_left;
- u32 actions_len_left;
- struct sk_buff *segs;
-
- segs = skb_gso_segment(skb, 0);
- kfree_skb(skb);
- if (IS_ERR(segs))
- return ERR_CAST(segs);
-
- actions_len_left = actions_len;
- actions_left = nla_next(a, &actions_len_left);
-
- do {
- struct sk_buff *nskb = segs->next;
- int err;
-
- segs->next = NULL;
-
- /* GSO can change the checksum type so update.*/
- compute_ip_summed(segs, true);
-
- segs = __vlan_put_tag(segs, ntohs(tci));
- err = -ENOMEM;
- if (segs) {
- err = execute_actions(
- dp, segs, key, actions_left,
- actions_len_left);
- }
-
- if (unlikely(err)) {
- while ((segs = nskb)) {
- nskb = segs->next;
- segs->next = NULL;
- kfree_skb(segs);
- }
- return ERR_PTR(err);
- }
-
- segs = nskb;
- } while (segs->next);
-
- skb = segs;
- compute_ip_summed(skb, true);
- }