Merge branch 'net-ufo-remove'
David S. Miller says: ==================== net: Remove UDP Fragmentation Offload support This is a patch series, based upon some discussions with various developers, that removes UFO offloading. Very few devices support this operation, it's usefullness is quesitonable at best, and it adds a non-trivial amount of complexity to our data paths. v2: Delete more code thanks to feedback from Willem. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
5c3c6081b2
|
@ -345,7 +345,7 @@ static void dummy_setup(struct net_device *dev)
|
|||
dev->flags &= ~IFF_MULTICAST;
|
||||
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
|
||||
dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST;
|
||||
dev->features |= NETIF_F_ALL_TSO | NETIF_F_UFO;
|
||||
dev->features |= NETIF_F_ALL_TSO;
|
||||
dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
|
||||
dev->features |= NETIF_F_GSO_ENCAP_ALL;
|
||||
dev->hw_features |= dev->features;
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
#define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
|
||||
|
||||
#define GEM_MTU_MIN_SIZE ETH_MIN_MTU
|
||||
#define MACB_NETIF_LSO (NETIF_F_TSO | NETIF_F_UFO)
|
||||
#define MACB_NETIF_LSO NETIF_F_TSO
|
||||
|
||||
#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0)
|
||||
#define MACB_WOL_ENABLED (0x1 << 1)
|
||||
|
|
|
@ -42,8 +42,6 @@
|
|||
* aggregated as a single large packet
|
||||
* napi: This parameter used to enable/disable NAPI (polling Rx)
|
||||
* Possible values '1' for enable and '0' for disable. Default is '1'
|
||||
* ufo: This parameter used to enable/disable UDP Fragmentation Offload(UFO)
|
||||
* Possible values '1' for enable and '0' for disable. Default is '0'
|
||||
* vlan_tag_strip: This can be used to enable or disable vlan stripping.
|
||||
* Possible values '1' for enable , '0' for disable.
|
||||
* Default is '2' - which means disable in promisc mode
|
||||
|
@ -453,7 +451,6 @@ S2IO_PARM_INT(lro_max_pkts, 0xFFFF);
|
|||
S2IO_PARM_INT(indicate_max_pkts, 0);
|
||||
|
||||
S2IO_PARM_INT(napi, 1);
|
||||
S2IO_PARM_INT(ufo, 0);
|
||||
S2IO_PARM_INT(vlan_tag_strip, NO_STRIP_IN_PROMISC);
|
||||
|
||||
static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
|
||||
|
@ -4128,32 +4125,6 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
}
|
||||
|
||||
frg_len = skb_headlen(skb);
|
||||
if (offload_type == SKB_GSO_UDP) {
|
||||
int ufo_size;
|
||||
|
||||
ufo_size = s2io_udp_mss(skb);
|
||||
ufo_size &= ~7;
|
||||
txdp->Control_1 |= TXD_UFO_EN;
|
||||
txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
|
||||
txdp->Control_1 |= TXD_BUFFER0_SIZE(8);
|
||||
#ifdef __BIG_ENDIAN
|
||||
/* both variants do cpu_to_be64(be32_to_cpu(...)) */
|
||||
fifo->ufo_in_band_v[put_off] =
|
||||
(__force u64)skb_shinfo(skb)->ip6_frag_id;
|
||||
#else
|
||||
fifo->ufo_in_band_v[put_off] =
|
||||
(__force u64)skb_shinfo(skb)->ip6_frag_id << 32;
|
||||
#endif
|
||||
txdp->Host_Control = (unsigned long)fifo->ufo_in_band_v;
|
||||
txdp->Buffer_Pointer = pci_map_single(sp->pdev,
|
||||
fifo->ufo_in_band_v,
|
||||
sizeof(u64),
|
||||
PCI_DMA_TODEVICE);
|
||||
if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer))
|
||||
goto pci_map_failed;
|
||||
txdp++;
|
||||
}
|
||||
|
||||
txdp->Buffer_Pointer = pci_map_single(sp->pdev, skb->data,
|
||||
frg_len, PCI_DMA_TODEVICE);
|
||||
if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer))
|
||||
|
@ -4161,8 +4132,6 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
txdp->Host_Control = (unsigned long)skb;
|
||||
txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
|
||||
if (offload_type == SKB_GSO_UDP)
|
||||
txdp->Control_1 |= TXD_UFO_EN;
|
||||
|
||||
frg_cnt = skb_shinfo(skb)->nr_frags;
|
||||
/* For fragmented SKB. */
|
||||
|
@ -4177,14 +4146,9 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
txdp->Control_1 = TXD_BUFFER0_SIZE(skb_frag_size(frag));
|
||||
if (offload_type == SKB_GSO_UDP)
|
||||
txdp->Control_1 |= TXD_UFO_EN;
|
||||
}
|
||||
txdp->Control_1 |= TXD_GATHER_CODE_LAST;
|
||||
|
||||
if (offload_type == SKB_GSO_UDP)
|
||||
frg_cnt++; /* as Txd0 was used for inband header */
|
||||
|
||||
tx_fifo = mac_control->tx_FIFO_start[queue];
|
||||
val64 = fifo->list_info[put_off].list_phy_addr;
|
||||
writeq(val64, &tx_fifo->TxDL_Pointer);
|
||||
|
@ -7910,11 +7874,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
|
|||
NETIF_F_RXCSUM | NETIF_F_LRO;
|
||||
dev->features |= dev->hw_features |
|
||||
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
|
||||
if (sp->device_type & XFRAME_II_DEVICE) {
|
||||
dev->hw_features |= NETIF_F_UFO;
|
||||
if (ufo)
|
||||
dev->features |= NETIF_F_UFO;
|
||||
}
|
||||
if (sp->high_dma_flag == true)
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
|
||||
|
@ -8147,10 +8106,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
|
|||
|
||||
DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
|
||||
dev->name);
|
||||
if (ufo)
|
||||
DBG_PRINT(ERR_DBG,
|
||||
"%s: UDP Fragmentation Offload(UFO) enabled\n",
|
||||
dev->name);
|
||||
/* Initialize device name */
|
||||
snprintf(sp->name, sizeof(sp->name), "%s Neterion %s", dev->name,
|
||||
sp->product_name);
|
||||
|
|
|
@ -169,7 +169,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
|
|||
|
||||
#define IPVLAN_FEATURES \
|
||||
(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
|
||||
NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
|
||||
NETIF_F_GSO | NETIF_F_TSO | NETIF_F_GSO_ROBUST | \
|
||||
NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
|
||||
NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <linux/virtio_net.h>
|
||||
|
||||
#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
|
||||
NETIF_F_TSO6 | NETIF_F_UFO)
|
||||
NETIF_F_TSO6)
|
||||
|
||||
static dev_t ipvtap_major;
|
||||
static struct cdev ipvtap_cdev;
|
||||
|
|
|
@ -841,7 +841,7 @@ static struct lock_class_key macvlan_netdev_addr_lock_key;
|
|||
|
||||
#define MACVLAN_FEATURES \
|
||||
(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
|
||||
NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_LRO | \
|
||||
NETIF_F_GSO | NETIF_F_TSO | NETIF_F_LRO | \
|
||||
NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
|
||||
NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ static struct class macvtap_class = {
|
|||
static struct cdev macvtap_cdev;
|
||||
|
||||
#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
|
||||
NETIF_F_TSO6 | NETIF_F_UFO)
|
||||
NETIF_F_TSO6)
|
||||
|
||||
static void macvtap_count_tx_dropped(struct tap_dev *tap)
|
||||
{
|
||||
|
|
|
@ -943,9 +943,6 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
|
|||
if (arg & TUN_F_TSO6)
|
||||
feature_mask |= NETIF_F_TSO6;
|
||||
}
|
||||
|
||||
if (arg & TUN_F_UFO)
|
||||
feature_mask |= NETIF_F_UFO;
|
||||
}
|
||||
|
||||
/* tun/tap driver inverts the usage for TSO offloads, where
|
||||
|
@ -956,7 +953,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
|
|||
* When user space turns off TSO, we turn off GSO/LRO so that
|
||||
* user-space will not receive TSO frames.
|
||||
*/
|
||||
if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO))
|
||||
if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
|
||||
features |= RX_OFFLOADS;
|
||||
else
|
||||
features &= ~RX_OFFLOADS;
|
||||
|
@ -1078,7 +1075,7 @@ static long tap_ioctl(struct file *file, unsigned int cmd,
|
|||
case TUNSETOFFLOAD:
|
||||
/* let the user check for future flags */
|
||||
if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
|
||||
TUN_F_TSO_ECN | TUN_F_UFO))
|
||||
TUN_F_TSO_ECN))
|
||||
return -EINVAL;
|
||||
|
||||
rtnl_lock();
|
||||
|
|
|
@ -199,7 +199,7 @@ struct tun_struct {
|
|||
struct net_device *dev;
|
||||
netdev_features_t set_features;
|
||||
#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
|
||||
NETIF_F_TSO6|NETIF_F_UFO)
|
||||
NETIF_F_TSO6)
|
||||
|
||||
int align;
|
||||
int vnet_hdr_sz;
|
||||
|
@ -1921,11 +1921,6 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
|
|||
features |= NETIF_F_TSO6;
|
||||
arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
|
||||
}
|
||||
|
||||
if (arg & TUN_F_UFO) {
|
||||
features |= NETIF_F_UFO;
|
||||
arg &= ~TUN_F_UFO;
|
||||
}
|
||||
}
|
||||
|
||||
/* This gives the user a way to test for new features in future by
|
||||
|
|
|
@ -2429,7 +2429,7 @@ static int virtnet_probe(struct virtio_device *vdev)
|
|||
dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
|
||||
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
|
||||
dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
|
||||
dev->hw_features |= NETIF_F_TSO
|
||||
| NETIF_F_TSO_ECN | NETIF_F_TSO6;
|
||||
}
|
||||
/* Individual feature bits: what can host handle? */
|
||||
|
@ -2439,13 +2439,11 @@ static int virtnet_probe(struct virtio_device *vdev)
|
|||
dev->hw_features |= NETIF_F_TSO6;
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
|
||||
dev->hw_features |= NETIF_F_TSO_ECN;
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
|
||||
dev->hw_features |= NETIF_F_UFO;
|
||||
|
||||
dev->features |= NETIF_F_GSO_ROBUST;
|
||||
|
||||
if (gso)
|
||||
dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO);
|
||||
dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
|
||||
/* (!csum && gso) case will be fixed by register_netdev() */
|
||||
}
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
|
||||
|
|
|
@ -36,7 +36,6 @@ enum {
|
|||
/**/NETIF_F_GSO_SHIFT, /* keep the order of SKB_GSO_* bits */
|
||||
NETIF_F_TSO_BIT /* ... TCPv4 segmentation */
|
||||
= NETIF_F_GSO_SHIFT,
|
||||
NETIF_F_UFO_BIT, /* ... UDPv4 fragmentation */
|
||||
NETIF_F_GSO_ROBUST_BIT, /* ... ->SKB_GSO_DODGY */
|
||||
NETIF_F_TSO_ECN_BIT, /* ... TCP ECN support */
|
||||
NETIF_F_TSO_MANGLEID_BIT, /* ... IPV4 ID mangling allowed */
|
||||
|
@ -118,7 +117,6 @@ enum {
|
|||
#define NETIF_F_TSO6 __NETIF_F(TSO6)
|
||||
#define NETIF_F_TSO_ECN __NETIF_F(TSO_ECN)
|
||||
#define NETIF_F_TSO __NETIF_F(TSO)
|
||||
#define NETIF_F_UFO __NETIF_F(UFO)
|
||||
#define NETIF_F_VLAN_CHALLENGED __NETIF_F(VLAN_CHALLENGED)
|
||||
#define NETIF_F_RXFCS __NETIF_F(RXFCS)
|
||||
#define NETIF_F_RXALL __NETIF_F(RXALL)
|
||||
|
@ -172,7 +170,7 @@ enum {
|
|||
NETIF_F_FSO)
|
||||
|
||||
/* List of features with software fallbacks. */
|
||||
#define NETIF_F_GSO_SOFTWARE (NETIF_F_ALL_TSO | NETIF_F_UFO | \
|
||||
#define NETIF_F_GSO_SOFTWARE (NETIF_F_ALL_TSO | \
|
||||
NETIF_F_GSO_SCTP)
|
||||
|
||||
/*
|
||||
|
|
|
@ -4098,7 +4098,6 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
|
|||
|
||||
/* check flags correspondence */
|
||||
BUILD_BUG_ON(SKB_GSO_TCPV4 != (NETIF_F_TSO >> NETIF_F_GSO_SHIFT));
|
||||
BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_UFO >> NETIF_F_GSO_SHIFT));
|
||||
BUILD_BUG_ON(SKB_GSO_DODGY != (NETIF_F_GSO_ROBUST >> NETIF_F_GSO_SHIFT));
|
||||
BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT));
|
||||
BUILD_BUG_ON(SKB_GSO_TCP_FIXEDID != (NETIF_F_TSO_MANGLEID >> NETIF_F_GSO_SHIFT));
|
||||
|
|
|
@ -463,39 +463,38 @@ enum {
|
|||
|
||||
enum {
|
||||
SKB_GSO_TCPV4 = 1 << 0,
|
||||
SKB_GSO_UDP = 1 << 1,
|
||||
|
||||
/* This indicates the skb is from an untrusted source. */
|
||||
SKB_GSO_DODGY = 1 << 2,
|
||||
SKB_GSO_DODGY = 1 << 1,
|
||||
|
||||
/* This indicates the tcp segment has CWR set. */
|
||||
SKB_GSO_TCP_ECN = 1 << 3,
|
||||
SKB_GSO_TCP_ECN = 1 << 2,
|
||||
|
||||
SKB_GSO_TCP_FIXEDID = 1 << 4,
|
||||
SKB_GSO_TCP_FIXEDID = 1 << 3,
|
||||
|
||||
SKB_GSO_TCPV6 = 1 << 5,
|
||||
SKB_GSO_TCPV6 = 1 << 4,
|
||||
|
||||
SKB_GSO_FCOE = 1 << 6,
|
||||
SKB_GSO_FCOE = 1 << 5,
|
||||
|
||||
SKB_GSO_GRE = 1 << 7,
|
||||
SKB_GSO_GRE = 1 << 6,
|
||||
|
||||
SKB_GSO_GRE_CSUM = 1 << 8,
|
||||
SKB_GSO_GRE_CSUM = 1 << 7,
|
||||
|
||||
SKB_GSO_IPXIP4 = 1 << 9,
|
||||
SKB_GSO_IPXIP4 = 1 << 8,
|
||||
|
||||
SKB_GSO_IPXIP6 = 1 << 10,
|
||||
SKB_GSO_IPXIP6 = 1 << 9,
|
||||
|
||||
SKB_GSO_UDP_TUNNEL = 1 << 11,
|
||||
SKB_GSO_UDP_TUNNEL = 1 << 10,
|
||||
|
||||
SKB_GSO_UDP_TUNNEL_CSUM = 1 << 12,
|
||||
SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
|
||||
|
||||
SKB_GSO_PARTIAL = 1 << 13,
|
||||
SKB_GSO_PARTIAL = 1 << 12,
|
||||
|
||||
SKB_GSO_TUNNEL_REMCSUM = 1 << 14,
|
||||
SKB_GSO_TUNNEL_REMCSUM = 1 << 13,
|
||||
|
||||
SKB_GSO_SCTP = 1 << 15,
|
||||
SKB_GSO_SCTP = 1 << 14,
|
||||
|
||||
SKB_GSO_ESP = 1 << 16,
|
||||
SKB_GSO_ESP = 1 << 15,
|
||||
};
|
||||
|
||||
#if BITS_PER_LONG > 32
|
||||
|
|
|
@ -18,9 +18,6 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
|
|||
case VIRTIO_NET_HDR_GSO_TCPV6:
|
||||
gso_type = SKB_GSO_TCPV6;
|
||||
break;
|
||||
case VIRTIO_NET_HDR_GSO_UDP:
|
||||
gso_type = SKB_GSO_UDP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -73,8 +70,6 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
|
|||
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
|
||||
else if (sinfo->gso_type & SKB_GSO_TCPV6)
|
||||
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
||||
else if (sinfo->gso_type & SKB_GSO_UDP)
|
||||
hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
|
||||
else
|
||||
return -EINVAL;
|
||||
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
|
||||
|
|
|
@ -7271,24 +7271,6 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
|
|||
features &= ~NETIF_F_GSO;
|
||||
}
|
||||
|
||||
/* UFO needs SG and checksumming */
|
||||
if (features & NETIF_F_UFO) {
|
||||
/* maybe split UFO into V4 and V6? */
|
||||
if (!(features & NETIF_F_HW_CSUM) &&
|
||||
((features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) !=
|
||||
(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))) {
|
||||
netdev_dbg(dev,
|
||||
"Dropping NETIF_F_UFO since no checksum offload features.\n");
|
||||
features &= ~NETIF_F_UFO;
|
||||
}
|
||||
|
||||
if (!(features & NETIF_F_SG)) {
|
||||
netdev_dbg(dev,
|
||||
"Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n");
|
||||
features &= ~NETIF_F_UFO;
|
||||
}
|
||||
}
|
||||
|
||||
/* GSO partial features require GSO partial be set */
|
||||
if ((features & dev->gso_partial_features) &&
|
||||
!(features & NETIF_F_GSO_PARTIAL)) {
|
||||
|
|
|
@ -76,7 +76,6 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
|
|||
[NETIF_F_LRO_BIT] = "rx-lro",
|
||||
|
||||
[NETIF_F_TSO_BIT] = "tx-tcp-segmentation",
|
||||
[NETIF_F_UFO_BIT] = "tx-udp-fragmentation",
|
||||
[NETIF_F_GSO_ROBUST_BIT] = "tx-gso-robust",
|
||||
[NETIF_F_TSO_ECN_BIT] = "tx-tcp-ecn-segmentation",
|
||||
[NETIF_F_TSO_MANGLEID_BIT] = "tx-tcp-mangleid-segmentation",
|
||||
|
@ -299,9 +298,6 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd)
|
|||
case ETHTOOL_GTSO:
|
||||
case ETHTOOL_STSO:
|
||||
return NETIF_F_ALL_TSO;
|
||||
case ETHTOOL_GUFO:
|
||||
case ETHTOOL_SUFO:
|
||||
return NETIF_F_UFO;
|
||||
case ETHTOOL_GGSO:
|
||||
case ETHTOOL_SGSO:
|
||||
return NETIF_F_GSO;
|
||||
|
@ -2555,7 +2551,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
|
|||
case ETHTOOL_GPHYSTATS:
|
||||
case ETHTOOL_GTSO:
|
||||
case ETHTOOL_GPERMADDR:
|
||||
case ETHTOOL_GUFO:
|
||||
case ETHTOOL_GGSO:
|
||||
case ETHTOOL_GGRO:
|
||||
case ETHTOOL_GFLAGS:
|
||||
|
@ -2723,7 +2718,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
|
|||
case ETHTOOL_GRXCSUM:
|
||||
case ETHTOOL_GSG:
|
||||
case ETHTOOL_GTSO:
|
||||
case ETHTOOL_GUFO:
|
||||
case ETHTOOL_GGSO:
|
||||
case ETHTOOL_GGRO:
|
||||
rc = ethtool_get_one_feature(dev, useraddr, ethcmd);
|
||||
|
@ -2732,7 +2726,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
|
|||
case ETHTOOL_SRXCSUM:
|
||||
case ETHTOOL_SSG:
|
||||
case ETHTOOL_STSO:
|
||||
case ETHTOOL_SUFO:
|
||||
case ETHTOOL_SGSO:
|
||||
case ETHTOOL_SGRO:
|
||||
rc = ethtool_set_one_feature(dev, useraddr, ethcmd);
|
||||
|
|
|
@ -2051,8 +2051,8 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
|
|||
return ret;
|
||||
|
||||
if (skb_is_gso(skb)) {
|
||||
/* SKB_GSO_UDP stays as is. SKB_GSO_TCPV4 needs to
|
||||
* be changed into SKB_GSO_TCPV6.
|
||||
/* SKB_GSO_TCPV4 needs to be changed into
|
||||
* SKB_GSO_TCPV6.
|
||||
*/
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
|
||||
skb_shinfo(skb)->gso_type &= ~SKB_GSO_TCPV4;
|
||||
|
@ -2087,8 +2087,8 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
|
|||
return ret;
|
||||
|
||||
if (skb_is_gso(skb)) {
|
||||
/* SKB_GSO_UDP stays as is. SKB_GSO_TCPV6 needs to
|
||||
* be changed into SKB_GSO_TCPV4.
|
||||
/* SKB_GSO_TCPV6 needs to be changed into
|
||||
* SKB_GSO_TCPV4.
|
||||
*/
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
|
||||
skb_shinfo(skb)->gso_type &= ~SKB_GSO_TCPV6;
|
||||
|
|
|
@ -1219,10 +1219,9 @@ EXPORT_SYMBOL(inet_sk_rebuild_header);
|
|||
struct sk_buff *inet_gso_segment(struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
bool udpfrag = false, fixedid = false, gso_partial, encap;
|
||||
bool fixedid = false, gso_partial, encap;
|
||||
struct sk_buff *segs = ERR_PTR(-EINVAL);
|
||||
const struct net_offload *ops;
|
||||
unsigned int offset = 0;
|
||||
struct iphdr *iph;
|
||||
int proto, tot_len;
|
||||
int nhoff;
|
||||
|
@ -1257,7 +1256,6 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
|
|||
segs = ERR_PTR(-EPROTONOSUPPORT);
|
||||
|
||||
if (!skb->encapsulation || encap) {
|
||||
udpfrag = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
|
||||
fixedid = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID);
|
||||
|
||||
/* fixed ID is invalid if DF bit is not set */
|
||||
|
@ -1277,13 +1275,7 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
|
|||
skb = segs;
|
||||
do {
|
||||
iph = (struct iphdr *)(skb_mac_header(skb) + nhoff);
|
||||
if (udpfrag) {
|
||||
iph->frag_off = htons(offset >> 3);
|
||||
if (skb->next)
|
||||
iph->frag_off |= htons(IP_MF);
|
||||
offset += skb->len - nhoff - ihl;
|
||||
tot_len = skb->len - nhoff;
|
||||
} else if (skb_is_gso(skb)) {
|
||||
if (skb_is_gso(skb)) {
|
||||
if (!fixedid) {
|
||||
iph->id = htons(id);
|
||||
id += skb_shinfo(skb)->gso_segs;
|
||||
|
|
|
@ -24,7 +24,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
|
|||
__be16 protocol = skb->protocol;
|
||||
u16 mac_len = skb->mac_len;
|
||||
int gre_offset, outer_hlen;
|
||||
bool need_csum, ufo, gso_partial;
|
||||
bool need_csum, gso_partial;
|
||||
|
||||
if (!skb->encapsulation)
|
||||
goto out;
|
||||
|
@ -47,20 +47,8 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
|
|||
need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_GRE_CSUM);
|
||||
skb->encap_hdr_csum = need_csum;
|
||||
|
||||
ufo = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
|
||||
|
||||
features &= skb->dev->hw_enc_features;
|
||||
|
||||
/* The only checksum offload we care about from here on out is the
|
||||
* outer one so strip the existing checksum feature flags based
|
||||
* on the fact that we will be computing our checksum in software.
|
||||
*/
|
||||
if (ufo) {
|
||||
features &= ~NETIF_F_CSUM_MASK;
|
||||
if (!need_csum)
|
||||
features |= NETIF_F_HW_CSUM;
|
||||
}
|
||||
|
||||
/* segment inner packet. */
|
||||
segs = skb_mac_gso_segment(skb, features);
|
||||
if (IS_ERR_OR_NULL(segs)) {
|
||||
|
|
|
@ -853,61 +853,6 @@ csum_page(struct page *page, int offset, int copy)
|
|||
return csum;
|
||||
}
|
||||
|
||||
static inline int ip_ufo_append_data(struct sock *sk,
|
||||
struct sk_buff_head *queue,
|
||||
int getfrag(void *from, char *to, int offset, int len,
|
||||
int odd, struct sk_buff *skb),
|
||||
void *from, int length, int hh_len, int fragheaderlen,
|
||||
int transhdrlen, int maxfraglen, unsigned int flags)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
/* There is support for UDP fragmentation offload by network
|
||||
* device, so create one single skb packet containing complete
|
||||
* udp datagram
|
||||
*/
|
||||
skb = skb_peek_tail(queue);
|
||||
if (!skb) {
|
||||
skb = sock_alloc_send_skb(sk,
|
||||
hh_len + fragheaderlen + transhdrlen + 20,
|
||||
(flags & MSG_DONTWAIT), &err);
|
||||
|
||||
if (!skb)
|
||||
return err;
|
||||
|
||||
/* reserve space for Hardware header */
|
||||
skb_reserve(skb, hh_len);
|
||||
|
||||
/* create space for UDP/IP header */
|
||||
skb_put(skb, fragheaderlen + transhdrlen);
|
||||
|
||||
/* initialize network header pointer */
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
/* initialize protocol header pointer */
|
||||
skb->transport_header = skb->network_header + fragheaderlen;
|
||||
|
||||
skb->csum = 0;
|
||||
|
||||
if (flags & MSG_CONFIRM)
|
||||
skb_set_dst_pending_confirm(skb, 1);
|
||||
|
||||
__skb_queue_tail(queue, skb);
|
||||
} else if (skb_is_gso(skb)) {
|
||||
goto append;
|
||||
}
|
||||
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
/* specify the length of each IP datagram fragment */
|
||||
skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||
|
||||
append:
|
||||
return skb_append_datato_frags(sk, skb, getfrag, from,
|
||||
(length - transhdrlen));
|
||||
}
|
||||
|
||||
static int __ip_append_data(struct sock *sk,
|
||||
struct flowi4 *fl4,
|
||||
struct sk_buff_head *queue,
|
||||
|
@ -965,18 +910,6 @@ static int __ip_append_data(struct sock *sk,
|
|||
csummode = CHECKSUM_PARTIAL;
|
||||
|
||||
cork->length += length;
|
||||
if ((((length + (skb ? skb->len : fragheaderlen)) > mtu) ||
|
||||
(skb && skb_is_gso(skb))) &&
|
||||
(sk->sk_protocol == IPPROTO_UDP) &&
|
||||
(rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
|
||||
(sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) {
|
||||
err = ip_ufo_append_data(sk, queue, getfrag, from, length,
|
||||
hh_len, fragheaderlen, transhdrlen,
|
||||
maxfraglen, flags);
|
||||
if (err)
|
||||
goto error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* So, what's going on in the loop below?
|
||||
*
|
||||
|
@ -1287,15 +1220,6 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
|
|||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
if ((size + skb->len > mtu) &&
|
||||
(sk->sk_protocol == IPPROTO_UDP) &&
|
||||
(rt->dst.dev->features & NETIF_F_UFO)) {
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||
}
|
||||
cork->length += size;
|
||||
|
||||
while (size > 0) {
|
||||
|
|
|
@ -21,7 +21,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
|||
__be16 new_protocol, bool is_ipv6)
|
||||
{
|
||||
int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
|
||||
bool remcsum, need_csum, offload_csum, ufo, gso_partial;
|
||||
bool remcsum, need_csum, offload_csum, gso_partial;
|
||||
struct sk_buff *segs = ERR_PTR(-EINVAL);
|
||||
struct udphdr *uh = udp_hdr(skb);
|
||||
u16 mac_offset = skb->mac_header;
|
||||
|
@ -61,8 +61,6 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
|||
remcsum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TUNNEL_REMCSUM);
|
||||
skb->remcsum_offload = remcsum;
|
||||
|
||||
ufo = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
|
||||
|
||||
need_ipsec = skb_dst(skb) && dst_xfrm(skb_dst(skb));
|
||||
/* Try to offload checksum if possible */
|
||||
offload_csum = !!(need_csum &&
|
||||
|
@ -77,7 +75,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
|||
* outer one so strip the existing checksum feature flags and
|
||||
* instead set the flag based on our outer checksum offload value.
|
||||
*/
|
||||
if (remcsum || ufo) {
|
||||
if (remcsum) {
|
||||
features &= ~NETIF_F_CSUM_MASK;
|
||||
if (!need_csum || offload_csum)
|
||||
features |= NETIF_F_HW_CSUM;
|
||||
|
@ -189,66 +187,16 @@ out_unlock:
|
|||
}
|
||||
EXPORT_SYMBOL(skb_udp_tunnel_segment);
|
||||
|
||||
static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
static struct sk_buff *udp4_tunnel_segment(struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
struct sk_buff *segs = ERR_PTR(-EINVAL);
|
||||
unsigned int mss;
|
||||
__wsum csum;
|
||||
struct udphdr *uh;
|
||||
struct iphdr *iph;
|
||||
|
||||
if (skb->encapsulation &&
|
||||
(skb_shinfo(skb)->gso_type &
|
||||
(SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))) {
|
||||
(SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM)))
|
||||
segs = skb_udp_tunnel_segment(skb, features, false);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct udphdr)))
|
||||
goto out;
|
||||
|
||||
mss = skb_shinfo(skb)->gso_size;
|
||||
if (unlikely(skb->len <= mss))
|
||||
goto out;
|
||||
|
||||
if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
|
||||
/* Packet is from an untrusted source, reset gso_segs. */
|
||||
|
||||
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
|
||||
|
||||
segs = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Do software UFO. Complete and fill in the UDP checksum as
|
||||
* HW cannot do checksum of UDP packets sent as multiple
|
||||
* IP fragments.
|
||||
*/
|
||||
|
||||
uh = udp_hdr(skb);
|
||||
iph = ip_hdr(skb);
|
||||
|
||||
uh->check = 0;
|
||||
csum = skb_checksum(skb, 0, skb->len, 0);
|
||||
uh->check = udp_v4_check(skb->len, iph->saddr, iph->daddr, csum);
|
||||
if (uh->check == 0)
|
||||
uh->check = CSUM_MANGLED_0;
|
||||
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
/* If there is no outer header we can fake a checksum offload
|
||||
* due to the fact that we have already done the checksum in
|
||||
* software prior to segmenting the frame.
|
||||
*/
|
||||
if (!skb->encap_hdr_csum)
|
||||
features |= NETIF_F_HW_CSUM;
|
||||
|
||||
/* Fragment the skb. IP headers of the fragments are updated in
|
||||
* inet_gso_segment()
|
||||
*/
|
||||
segs = skb_segment(skb, features);
|
||||
out:
|
||||
return segs;
|
||||
}
|
||||
|
||||
|
@ -382,7 +330,7 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
|
|||
|
||||
static const struct net_offload udpv4_offload = {
|
||||
.callbacks = {
|
||||
.gso_segment = udp4_ufo_fragment,
|
||||
.gso_segment = udp4_tunnel_segment,
|
||||
.gro_receive = udp4_gro_receive,
|
||||
.gro_complete = udp4_gro_complete,
|
||||
},
|
||||
|
|
|
@ -1114,69 +1114,6 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
|
||||
|
||||
static inline int ip6_ufo_append_data(struct sock *sk,
|
||||
struct sk_buff_head *queue,
|
||||
int getfrag(void *from, char *to, int offset, int len,
|
||||
int odd, struct sk_buff *skb),
|
||||
void *from, int length, int hh_len, int fragheaderlen,
|
||||
int exthdrlen, int transhdrlen, int mtu,
|
||||
unsigned int flags, const struct flowi6 *fl6)
|
||||
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
/* There is support for UDP large send offload by network
|
||||
* device, so create one single skb packet containing complete
|
||||
* udp datagram
|
||||
*/
|
||||
skb = skb_peek_tail(queue);
|
||||
if (!skb) {
|
||||
skb = sock_alloc_send_skb(sk,
|
||||
hh_len + fragheaderlen + transhdrlen + 20,
|
||||
(flags & MSG_DONTWAIT), &err);
|
||||
if (!skb)
|
||||
return err;
|
||||
|
||||
/* reserve space for Hardware header */
|
||||
skb_reserve(skb, hh_len);
|
||||
|
||||
/* create space for UDP/IP header */
|
||||
skb_put(skb, fragheaderlen + transhdrlen);
|
||||
|
||||
/* initialize network header pointer */
|
||||
skb_set_network_header(skb, exthdrlen);
|
||||
|
||||
/* initialize protocol header pointer */
|
||||
skb->transport_header = skb->network_header + fragheaderlen;
|
||||
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
skb->csum = 0;
|
||||
|
||||
if (flags & MSG_CONFIRM)
|
||||
skb_set_dst_pending_confirm(skb, 1);
|
||||
|
||||
__skb_queue_tail(queue, skb);
|
||||
} else if (skb_is_gso(skb)) {
|
||||
goto append;
|
||||
}
|
||||
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
/* Specify the length of each IPv6 datagram fragment.
|
||||
* It has to be a multiple of 8.
|
||||
*/
|
||||
skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
|
||||
sizeof(struct frag_hdr)) & ~7;
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||
skb_shinfo(skb)->ip6_frag_id = ipv6_select_ident(sock_net(sk),
|
||||
&fl6->daddr,
|
||||
&fl6->saddr);
|
||||
|
||||
append:
|
||||
return skb_append_datato_frags(sk, skb, getfrag, from,
|
||||
(length - transhdrlen));
|
||||
}
|
||||
|
||||
static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
|
||||
gfp_t gfp)
|
||||
{
|
||||
|
@ -1385,19 +1322,6 @@ emsgsize:
|
|||
*/
|
||||
|
||||
cork->length += length;
|
||||
if ((((length + (skb ? skb->len : headersize)) > mtu) ||
|
||||
(skb && skb_is_gso(skb))) &&
|
||||
(sk->sk_protocol == IPPROTO_UDP) &&
|
||||
(rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
|
||||
(sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) {
|
||||
err = ip6_ufo_append_data(sk, queue, getfrag, from, length,
|
||||
hh_len, fragheaderlen, exthdrlen,
|
||||
transhdrlen, mtu, flags, fl6);
|
||||
if (err)
|
||||
goto error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!skb)
|
||||
goto alloc_new_skb;
|
||||
|
||||
|
|
|
@ -17,109 +17,15 @@
|
|||
#include <net/ip6_checksum.h>
|
||||
#include "ip6_offload.h"
|
||||
|
||||
static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
static struct sk_buff *udp6_tunnel_segment(struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
struct sk_buff *segs = ERR_PTR(-EINVAL);
|
||||
unsigned int mss;
|
||||
unsigned int unfrag_ip6hlen, unfrag_len;
|
||||
struct frag_hdr *fptr;
|
||||
u8 *packet_start, *prevhdr;
|
||||
u8 nexthdr;
|
||||
u8 frag_hdr_sz = sizeof(struct frag_hdr);
|
||||
__wsum csum;
|
||||
int tnl_hlen;
|
||||
int err;
|
||||
|
||||
mss = skb_shinfo(skb)->gso_size;
|
||||
if (unlikely(skb->len <= mss))
|
||||
goto out;
|
||||
|
||||
if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
|
||||
/* Packet is from an untrusted source, reset gso_segs. */
|
||||
|
||||
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
|
||||
|
||||
/* Set the IPv6 fragment id if not set yet */
|
||||
if (!skb_shinfo(skb)->ip6_frag_id)
|
||||
ipv6_proxy_select_ident(dev_net(skb->dev), skb);
|
||||
|
||||
segs = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (skb->encapsulation && skb_shinfo(skb)->gso_type &
|
||||
(SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))
|
||||
segs = skb_udp_tunnel_segment(skb, features, true);
|
||||
else {
|
||||
const struct ipv6hdr *ipv6h;
|
||||
struct udphdr *uh;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct udphdr)))
|
||||
goto out;
|
||||
|
||||
/* Do software UFO. Complete and fill in the UDP checksum as HW cannot
|
||||
* do checksum of UDP packets sent as multiple IP fragments.
|
||||
*/
|
||||
|
||||
uh = udp_hdr(skb);
|
||||
ipv6h = ipv6_hdr(skb);
|
||||
|
||||
uh->check = 0;
|
||||
csum = skb_checksum(skb, 0, skb->len, 0);
|
||||
uh->check = udp_v6_check(skb->len, &ipv6h->saddr,
|
||||
&ipv6h->daddr, csum);
|
||||
if (uh->check == 0)
|
||||
uh->check = CSUM_MANGLED_0;
|
||||
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
/* If there is no outer header we can fake a checksum offload
|
||||
* due to the fact that we have already done the checksum in
|
||||
* software prior to segmenting the frame.
|
||||
*/
|
||||
if (!skb->encap_hdr_csum)
|
||||
features |= NETIF_F_HW_CSUM;
|
||||
|
||||
/* Check if there is enough headroom to insert fragment header. */
|
||||
tnl_hlen = skb_tnl_header_len(skb);
|
||||
if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) {
|
||||
if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Find the unfragmentable header and shift it left by frag_hdr_sz
|
||||
* bytes to insert fragment header.
|
||||
*/
|
||||
err = ip6_find_1stfragopt(skb, &prevhdr);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
unfrag_ip6hlen = err;
|
||||
nexthdr = *prevhdr;
|
||||
*prevhdr = NEXTHDR_FRAGMENT;
|
||||
unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
|
||||
unfrag_ip6hlen + tnl_hlen;
|
||||
packet_start = (u8 *) skb->head + SKB_GSO_CB(skb)->mac_offset;
|
||||
memmove(packet_start-frag_hdr_sz, packet_start, unfrag_len);
|
||||
|
||||
SKB_GSO_CB(skb)->mac_offset -= frag_hdr_sz;
|
||||
skb->mac_header -= frag_hdr_sz;
|
||||
skb->network_header -= frag_hdr_sz;
|
||||
|
||||
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
|
||||
fptr->nexthdr = nexthdr;
|
||||
fptr->reserved = 0;
|
||||
if (!skb_shinfo(skb)->ip6_frag_id)
|
||||
ipv6_proxy_select_ident(dev_net(skb->dev), skb);
|
||||
fptr->identification = skb_shinfo(skb)->ip6_frag_id;
|
||||
|
||||
/* Fragment the skb. ipv6 header and the remaining fields of the
|
||||
* fragment header are updated in ipv6_gso_segment()
|
||||
*/
|
||||
segs = skb_segment(skb, features);
|
||||
}
|
||||
|
||||
out:
|
||||
return segs;
|
||||
}
|
||||
|
||||
|
@ -169,7 +75,7 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff)
|
|||
|
||||
static const struct net_offload udpv6_offload = {
|
||||
.callbacks = {
|
||||
.gso_segment = udp6_ufo_fragment,
|
||||
.gso_segment = udp6_tunnel_segment,
|
||||
.gro_receive = udp6_gro_receive,
|
||||
.gro_complete = udp6_gro_complete,
|
||||
},
|
||||
|
|
|
@ -335,8 +335,6 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
|
|||
const struct dp_upcall_info *upcall_info,
|
||||
uint32_t cutlen)
|
||||
{
|
||||
unsigned short gso_type = skb_shinfo(skb)->gso_type;
|
||||
struct sw_flow_key later_key;
|
||||
struct sk_buff *segs, *nskb;
|
||||
int err;
|
||||
|
||||
|
@ -347,21 +345,9 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
|
|||
if (segs == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (gso_type & SKB_GSO_UDP) {
|
||||
/* The initial flow key extracted by ovs_flow_key_extract()
|
||||
* in this case is for a first fragment, so we need to
|
||||
* properly mark later fragments.
|
||||
*/
|
||||
later_key = *key;
|
||||
later_key.ip.frag = OVS_FRAG_TYPE_LATER;
|
||||
}
|
||||
|
||||
/* Queue all of the segments. */
|
||||
skb = segs;
|
||||
do {
|
||||
if (gso_type & SKB_GSO_UDP && skb != segs)
|
||||
key = &later_key;
|
||||
|
||||
err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen);
|
||||
if (err)
|
||||
break;
|
||||
|
|
|
@ -584,8 +584,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
|||
key->ip.frag = OVS_FRAG_TYPE_LATER;
|
||||
return 0;
|
||||
}
|
||||
if (nh->frag_off & htons(IP_MF) ||
|
||||
skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
|
||||
if (nh->frag_off & htons(IP_MF))
|
||||
key->ip.frag = OVS_FRAG_TYPE_FIRST;
|
||||
else
|
||||
key->ip.frag = OVS_FRAG_TYPE_NONE;
|
||||
|
@ -701,9 +700,6 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
|||
|
||||
if (key->ip.frag == OVS_FRAG_TYPE_LATER)
|
||||
return 0;
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
|
||||
key->ip.frag = OVS_FRAG_TYPE_FIRST;
|
||||
|
||||
/* Transport layer. */
|
||||
if (key->ip.proto == NEXTHDR_TCP) {
|
||||
if (tcphdr_ok(skb)) {
|
||||
|
|
|
@ -231,9 +231,6 @@ static int tcf_csum_ipv4_udp(struct sk_buff *skb, unsigned int ihl,
|
|||
const struct iphdr *iph;
|
||||
u16 ul;
|
||||
|
||||
if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Support both UDP and UDPLITE checksum algorithms, Don't use
|
||||
* udph->len to get the real length without any protocol check,
|
||||
|
@ -287,9 +284,6 @@ static int tcf_csum_ipv6_udp(struct sk_buff *skb, unsigned int ihl,
|
|||
const struct ipv6hdr *ip6h;
|
||||
u16 ul;
|
||||
|
||||
if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Support both UDP and UDPLITE checksum algorithms, Don't use
|
||||
* udph->len to get the real length without any protocol check,
|
||||
|
|
Загрузка…
Ссылка в новой задаче