--- zzzz-none-000/linux-4.9.276/net/ethernet/eth.c 2021-07-20 14:21:16.000000000 +0000 +++ falcon-5530-750/linux-4.9.276/net/ethernet/eth.c 2023-04-05 08:19:02.000000000 +0000 @@ -143,6 +143,18 @@ } EXPORT_SYMBOL(eth_get_headlen); +static inline bool +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask) +{ + const u16 *a1 = addr1; + const u16 *a2 = addr2; + const u16 *m = mask; + + return (((a1[0] ^ a2[0]) & ~m[0]) | + ((a1[1] ^ a2[1]) & ~m[1]) | + ((a1[2] ^ a2[2]) & ~m[2])); +} + /** * eth_type_trans - determine the packet's protocol ID. * @skb: received socket data @@ -159,6 +171,12 @@ const struct ethhdr *eth; skb->dev = dev; + +#ifdef CONFIG_ETHERNET_PACKET_MANGLE + if (dev->eth_mangle_rx) + dev->eth_mangle_rx(dev, skb); +#endif + skb_reset_mac_header(skb); eth = (struct ethhdr *)skb->data; @@ -169,10 +187,13 @@ skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_MULTICAST; - } - else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, - dev->dev_addr))) + } else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, + dev->dev_addr))) { skb->pkt_type = PACKET_OTHERHOST; + if (eth_check_local_mask(eth->h_dest, dev->dev_addr, + dev->local_addr_mask)) + skb->gro_skip = 1; + } /* * Some variants of DSA tagging don't have an ethertype field @@ -396,6 +417,34 @@ } EXPORT_SYMBOL(alloc_etherdev_mqs); +static void devm_free_netdev(struct device *dev, void *res) +{ + free_netdev(*(struct net_device **)res); +} + +struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv, + unsigned int txqs, unsigned int rxqs) +{ + struct net_device **dr; + struct net_device *netdev; + + dr = devres_alloc(devm_free_netdev, sizeof(*dr), GFP_KERNEL); + if (!dr) + return NULL; + + netdev = alloc_etherdev_mqs(sizeof_priv, txqs, rxqs); + if (!netdev) { + devres_free(dr); + return NULL; + } + + *dr = netdev; + devres_add(dev, dr); + + return netdev; +} +EXPORT_SYMBOL(devm_alloc_etherdev_mqs); + ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len) { return scnprintf(buf, PAGE_SIZE, "%*phC\n", len, addr);