Merge branch 'neigh_cleanups'
authorDavid S. Miller <davem@davemloft.net>
Mon, 2 Mar 2015 21:43:46 +0000 (16:43 -0500)
committerDavid S. Miller <davem@davemloft.net>
Mon, 2 Mar 2015 21:43:46 +0000 (16:43 -0500)
Eric W. Biederman says:

====================
Neighbour table and ax25 cleanups

While looking at the neighbour table to what it would take to allow
using next hops in a different address family than the current packets
I found a partial resolution for my issues and I stumbled upon some
work that makes the neighbour table code easier to understand and
maintain.

Long ago in a much younger kernel ax25 found a hack to use
dev_rebuild_header to transmit it's packets instead of going through
what today is ndo_start_xmit.

When the neighbour table was rewritten into it's current form the ax25
code was such a challenge that arp_broken_ops appeard in arp.c and
neigh_compat_output appeared in neighbour.c to keep the ax25 hack alive.

With a little bit of work I was able to remove some of the hack that
is the ax25 transmit path for ip packets and to isolate what remains
into a slightly more readable piece of code in ax25_ip.c.  Removing the
need for the generic code to worry about ax25 special cases.

After cleaning up the old ax25 hacks I also performed a little bit of
work on neigh_resolve_output to remove the need for a dst entry and to
ensure cached headers get a deterministic protocol value in their cached
header.   This guarantees that a cached header will not be different
depending on which protocol of packet is transmitted, and it allows
packets to be transmitted that don't have a dst entry.  There remains
a small amount of code that takes advantage of when packets have a dst
entry but that is something different.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
32 files changed:
drivers/firewire/net.c
drivers/isdn/i4l/isdn_net.c
drivers/media/dvb-core/dvb_net.c
drivers/net/arcnet/arcnet.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/dmascc.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macvlan.c
drivers/net/wireless/hostap/hostap_main.c
include/linux/etherdevice.h
include/linux/netdevice.h
include/net/arp.h
include/net/ax25.h
include/net/neighbour.h
net/802/fc.c
net/802/fddi.c
net/802/hippi.c
net/8021q/vlan_dev.c
net/ax25/ax25_ip.c
net/core/neighbour.c
net/decnet/dn_neigh.c
net/ethernet/eth.c
net/ipv4/arp.c
net/ipv6/ndisc.c
net/netrom/nr_dev.c
net/rose/rose_dev.c

index 2c68da1ceeeef9ac39c272e0309dbb7ed9c85514..f4ea80d602f73bd6bc5adac2a32bbbe2b58de716 100644 (file)
@@ -237,18 +237,6 @@ static int fwnet_header_create(struct sk_buff *skb, struct net_device *net,
        return -net->hard_header_len;
 }
 
-static int fwnet_header_rebuild(struct sk_buff *skb)
-{
-       struct fwnet_header *h = (struct fwnet_header *)skb->data;
-
-       if (get_unaligned_be16(&h->h_proto) == ETH_P_IP)
-               return arp_find((unsigned char *)&h->h_dest, skb);
-
-       dev_notice(&skb->dev->dev, "unable to resolve type %04x addresses\n",
-                  be16_to_cpu(h->h_proto));
-       return 0;
-}
-
 static int fwnet_header_cache(const struct neighbour *neigh,
                              struct hh_cache *hh, __be16 type)
 {
@@ -282,7 +270,6 @@ static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr)
 
 static const struct header_ops fwnet_header_ops = {
        .create         = fwnet_header_create,
-       .rebuild        = fwnet_header_rebuild,
        .cache          = fwnet_header_cache,
        .cache_update   = fwnet_header_cache_update,
        .parse          = fwnet_header_parse,
index 94affa5e6f2895725c6f61c9d53b8b988b1a9bca..546b7e81161dd21df253aa7d5f0f41722a30c15e 100644 (file)
@@ -1951,38 +1951,6 @@ static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
        return len;
 }
 
-/* We don't need to send arp, because we have point-to-point connections. */
-static int
-isdn_net_rebuild_header(struct sk_buff *skb)
-{
-       struct net_device *dev = skb->dev;
-       isdn_net_local *lp = netdev_priv(dev);
-       int ret = 0;
-
-       if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
-               struct ethhdr *eth = (struct ethhdr *) skb->data;
-
-               /*
-                *      Only ARP/IP is currently supported
-                */
-
-               if (eth->h_proto != htons(ETH_P_IP)) {
-                       printk(KERN_WARNING
-                              "isdn_net: %s don't know how to resolve type %d addresses?\n",
-                              dev->name, (int) eth->h_proto);
-                       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-                       return 0;
-               }
-               /*
-                *      Try to get ARP to resolve the header.
-                */
-#ifdef CONFIG_INET
-               ret = arp_find(eth->h_dest, skb);
-#endif
-       }
-       return ret;
-}
-
 static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
                             __be16 type)
 {
@@ -2005,7 +1973,6 @@ static void isdn_header_cache_update(struct hh_cache *hh,
 
 static const struct header_ops isdn_header_ops = {
        .create = isdn_net_header,
-       .rebuild = isdn_net_rebuild_header,
        .cache = isdn_header_cache,
        .cache_update = isdn_header_cache_update,
 };
index 686d3277dad123113d5464b1f00bb4e5b3d8b069..4a77cb02dffc3edeb42cc8cff8c8ad10af38306b 100644 (file)
@@ -1190,7 +1190,6 @@ static int dvb_net_stop(struct net_device *dev)
 static const struct header_ops dvb_header_ops = {
        .create         = eth_header,
        .parse          = eth_header_parse,
-       .rebuild        = eth_rebuild_header,
 };
 
 
index 09de683c167ecf692ac5178644e46b96ac3d7853..10f71c732b5995c9121acf41724848f49994b49f 100644 (file)
@@ -104,7 +104,6 @@ EXPORT_SYMBOL(arcnet_timeout);
 static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
                         unsigned short type, const void *daddr,
                         const void *saddr, unsigned len);
-static int arcnet_rebuild_header(struct sk_buff *skb);
 static int go_tx(struct net_device *dev);
 
 static int debug = ARCNET_DEBUG;
@@ -312,7 +311,6 @@ static int choose_mtu(void)
 
 static const struct header_ops arcnet_header_ops = {
        .create = arcnet_header,
-       .rebuild = arcnet_rebuild_header,
 };
 
 static const struct net_device_ops arcnet_netdev_ops = {
@@ -538,59 +536,6 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
        return proto->build_header(skb, dev, type, _daddr);
 }
 
-
-/* 
- * Rebuild the ARCnet hard header. This is called after an ARP (or in the
- * future other address resolution) has completed on this sk_buff. We now
- * let ARP fill in the destination field.
- */
-static int arcnet_rebuild_header(struct sk_buff *skb)
-{
-       struct net_device *dev = skb->dev;
-       struct arcnet_local *lp = netdev_priv(dev);
-       int status = 0;         /* default is failure */
-       unsigned short type;
-       uint8_t daddr=0;
-       struct ArcProto *proto;
-       /*
-        * XXX: Why not use skb->mac_len?
-        */
-       if (skb->network_header - skb->mac_header != 2) {
-               BUGMSG(D_NORMAL,
-                      "rebuild_header: shouldn't be here! (hdrsize=%d)\n",
-                      (int)(skb->network_header - skb->mac_header));
-               return 0;
-       }
-       type = *(uint16_t *) skb_pull(skb, 2);
-       BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type);
-
-       if (type == ETH_P_IP) {
-#ifdef CONFIG_INET
-               BUGMSG(D_DURING, "rebuild header for ethernet protocol %Xh\n", type);
-               status = arp_find(&daddr, skb) ? 1 : 0;
-               BUGMSG(D_DURING, " rebuilt: dest is %d; protocol %Xh\n",
-                      daddr, type);
-#endif
-       } else {
-               BUGMSG(D_NORMAL,
-                      "I don't understand ethernet protocol %Xh addresses!\n", type);
-               dev->stats.tx_errors++;
-               dev->stats.tx_aborted_errors++;
-       }
-
-       /* if we couldn't resolve the address... give up. */
-       if (!status)
-               return 0;
-
-       /* add the _real_ header this time! */
-       proto = arc_proto_map[lp->default_proto[daddr]];
-       proto->build_header(skb, dev, type, daddr);
-
-       return 1;               /* success */
-}
-
-
-
 /* Called by the kernel in order to transmit a packet. */
 netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
                                     struct net_device *dev)
index daca0dee88f3634570ab6cf984e80066bd331341..0b8393ca8c80134b444e5d3bf69d3ed58552b644 100644 (file)
@@ -284,18 +284,6 @@ static int sp_close(struct net_device *dev)
        return 0;
 }
 
-/* Return the frame type ID */
-static int sp_header(struct sk_buff *skb, struct net_device *dev,
-                    unsigned short type, const void *daddr,
-                    const void *saddr, unsigned len)
-{
-#ifdef CONFIG_INET
-       if (type != ETH_P_AX25)
-               return ax25_hard_header(skb, dev, type, daddr, saddr, len);
-#endif
-       return 0;
-}
-
 static int sp_set_mac_address(struct net_device *dev, void *addr)
 {
        struct sockaddr_ax25 *sa = addr;
@@ -309,25 +297,12 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
        return 0;
 }
 
-static int sp_rebuild_header(struct sk_buff *skb)
-{
-#ifdef CONFIG_INET
-       return ax25_rebuild_header(skb);
-#else
-       return 0;
-#endif
-}
-
-static const struct header_ops sp_header_ops = {
-       .create         = sp_header,
-       .rebuild        = sp_rebuild_header,
-};
-
 static const struct net_device_ops sp_netdev_ops = {
        .ndo_open               = sp_open_dev,
        .ndo_stop               = sp_close,
        .ndo_start_xmit         = sp_xmit,
        .ndo_set_mac_address    = sp_set_mac_address,
+       .ndo_neigh_construct    = ax25_neigh_construct,
 };
 
 static void sp_setup(struct net_device *dev)
@@ -337,10 +312,11 @@ static void sp_setup(struct net_device *dev)
        dev->destructor         = free_netdev;
        dev->mtu                = SIXP_MTU;
        dev->hard_header_len    = AX25_MAX_HEADER_LEN;
-       dev->header_ops         = &sp_header_ops;
+       dev->header_ops         = &ax25_header_ops;
 
        dev->addr_len           = AX25_ADDR_LEN;
        dev->type               = ARPHRD_AX25;
+       dev->neigh_priv_len     = sizeof(struct ax25_neigh_priv);
        dev->tx_queue_len       = 10;
 
        /* Only activated in AX.25 mode */
index a98c153f371e761f2c396c7fbcc1bdf787f407f3..3539ab392f7dc9af3713a6dfd4ec1e978537f470 100644 (file)
@@ -1109,6 +1109,7 @@ static const struct net_device_ops baycom_netdev_ops = {
        .ndo_do_ioctl        = baycom_ioctl,
        .ndo_start_xmit      = baycom_send_packet,
        .ndo_set_mac_address = baycom_set_mac_address,
+       .ndo_neigh_construct = ax25_neigh_construct,
 };
 
 /*
@@ -1146,6 +1147,7 @@ static void baycom_probe(struct net_device *dev)
        dev->header_ops = &ax25_header_ops;
        
        dev->type = ARPHRD_AX25;           /* AF_AX25 device */
+       dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
        dev->mtu = AX25_DEF_PACLEN;        /* eth_mtu is the default */
        dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */
index c2894e43840e604e75eac9f40bcfb1470e4c47aa..bce105b16ed0771460e1a03205c1bb64b213f2bb 100644 (file)
@@ -469,6 +469,7 @@ static const struct net_device_ops bpq_netdev_ops = {
        .ndo_start_xmit      = bpq_xmit,
        .ndo_set_mac_address = bpq_set_mac_address,
        .ndo_do_ioctl        = bpq_ioctl,
+       .ndo_neigh_construct = ax25_neigh_construct,
 };
 
 static void bpq_setup(struct net_device *dev)
@@ -486,6 +487,7 @@ static void bpq_setup(struct net_device *dev)
 #endif
 
        dev->type            = ARPHRD_AX25;
+       dev->neigh_priv_len  = sizeof(struct ax25_neigh_priv);
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
        dev->mtu             = AX25_DEF_PACLEN;
        dev->addr_len        = AX25_ADDR_LEN;
index 0fad408f24aa137694156290ae35a1da99343b80..abab7be77406387fd8442908bfcbe6989d76d083 100644 (file)
@@ -433,6 +433,7 @@ module_exit(dmascc_exit);
 static void __init dev_setup(struct net_device *dev)
 {
        dev->type = ARPHRD_AX25;
+       dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
        dev->hard_header_len = AX25_MAX_HEADER_LEN;
        dev->mtu = 1500;
        dev->addr_len = AX25_ADDR_LEN;
@@ -447,6 +448,7 @@ static const struct net_device_ops scc_netdev_ops = {
        .ndo_start_xmit = scc_send_packet,
        .ndo_do_ioctl = scc_ioctl,
        .ndo_set_mac_address = scc_set_mac_address,
+       .ndo_neigh_construct = ax25_neigh_construct,
 };
 
 static int __init setup_adapter(int card_base, int type, int n)
index c67a27245072746c3275a3b27a4fd899ebb6f3a4..435868a7b69cdcdde15d05988adb1f66f737fa11 100644 (file)
@@ -626,6 +626,7 @@ static const struct net_device_ops hdlcdrv_netdev = {
        .ndo_start_xmit = hdlcdrv_send_packet,
        .ndo_do_ioctl   = hdlcdrv_ioctl,
        .ndo_set_mac_address = hdlcdrv_set_mac_address,
+       .ndo_neigh_construct = ax25_neigh_construct,
 };
 
 /*
@@ -676,6 +677,7 @@ static void hdlcdrv_setup(struct net_device *dev)
        dev->header_ops = &ax25_header_ops;
        
        dev->type = ARPHRD_AX25;           /* AF_AX25 device */
+       dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
        dev->mtu = AX25_DEF_PACLEN;        /* eth_mtu is the default */
        dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */
index f990bb1c3e02ba50c583e6d41d3f8472736a3e37..c12ec2c2b594a79e941ea7a9256c3bc5f8cc8c32 100644 (file)
@@ -573,32 +573,6 @@ static int ax_open_dev(struct net_device *dev)
        return 0;
 }
 
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-
-/* Return the frame type ID */
-static int ax_header(struct sk_buff *skb, struct net_device *dev,
-                    unsigned short type, const void *daddr,
-                    const void *saddr, unsigned len)
-{
-#ifdef CONFIG_INET
-       if (type != ETH_P_AX25)
-               return ax25_hard_header(skb, dev, type, daddr, saddr, len);
-#endif
-       return 0;
-}
-
-
-static int ax_rebuild_header(struct sk_buff *skb)
-{
-#ifdef CONFIG_INET
-       return ax25_rebuild_header(skb);
-#else
-       return 0;
-#endif
-}
-
-#endif /* CONFIG_{AX25,AX25_MODULE} */
-
 /* Open the low-level part of the AX25 channel. Easy! */
 static int ax_open(struct net_device *dev)
 {
@@ -662,16 +636,12 @@ static int ax_close(struct net_device *dev)
        return 0;
 }
 
-static const struct header_ops ax_header_ops = {
-       .create    = ax_header,
-       .rebuild   = ax_rebuild_header,
-};
-
 static const struct net_device_ops ax_netdev_ops = {
        .ndo_open            = ax_open_dev,
        .ndo_stop            = ax_close,
        .ndo_start_xmit      = ax_xmit,
        .ndo_set_mac_address = ax_set_mac_address,
+       .ndo_neigh_construct = ax25_neigh_construct,
 };
 
 static void ax_setup(struct net_device *dev)
@@ -681,8 +651,9 @@ static void ax_setup(struct net_device *dev)
        dev->hard_header_len = 0;
        dev->addr_len        = 0;
        dev->type            = ARPHRD_AX25;
+       dev->neigh_priv_len  = sizeof(struct ax25_neigh_priv);
        dev->tx_queue_len    = 10;
-       dev->header_ops      = &ax_header_ops;
+       dev->header_ops      = &ax25_header_ops;
        dev->netdev_ops      = &ax_netdev_ops;
 
 
index 57be9e0e98a68608fcbafade768bcf397b248e42..b305f51eb42015316b7943f382165ad36c847408 100644 (file)
@@ -1550,6 +1550,7 @@ static const struct net_device_ops scc_netdev_ops = {
        .ndo_set_mac_address = scc_net_set_mac_address,
        .ndo_get_stats       = scc_net_get_stats,
        .ndo_do_ioctl        = scc_net_ioctl,
+       .ndo_neigh_construct = ax25_neigh_construct,
 };
 
 /* ----> Initialize device <----- */
@@ -1567,6 +1568,7 @@ static void scc_net_setup(struct net_device *dev)
        dev->flags      = 0;
 
        dev->type = ARPHRD_AX25;
+       dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
        dev->mtu = AX25_DEF_PACLEN;
        dev->addr_len = AX25_ADDR_LEN;
index 717433cfb81d2c4248539a56516daf6eb09c45ae..89d9da7a0c51eebf7fa4b338d21f8a85119ac3eb 100644 (file)
@@ -1100,6 +1100,7 @@ static const struct net_device_ops yam_netdev_ops = {
        .ndo_start_xmit      = yam_send_packet,
        .ndo_do_ioctl        = yam_ioctl,
        .ndo_set_mac_address = yam_set_mac_address,
+       .ndo_neigh_construct = ax25_neigh_construct,
 };
 
 static void yam_setup(struct net_device *dev)
@@ -1128,6 +1129,7 @@ static void yam_setup(struct net_device *dev)
        dev->header_ops = &ax25_header_ops;
 
        dev->type = ARPHRD_AX25;
+       dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
        dev->hard_header_len = AX25_MAX_HEADER_LEN;
        dev->mtu = AX25_MTU;
        dev->addr_len = AX25_ADDR_LEN;
index 4f4099d5603d0b64f2a15b66e86dbee90260cead..2950c3780230596270aa64d0ebac69f7c1bd3cbd 100644 (file)
@@ -336,7 +336,6 @@ static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
 
 static const struct header_ops ipvlan_header_ops = {
        .create         = ipvlan_hard_header,
-       .rebuild        = eth_rebuild_header,
        .parse          = eth_header_parse,
        .cache          = eth_header_cache,
        .cache_update   = eth_header_cache_update,
index 1df38bdae2ee384d1c6285a699b7dbf31dd28f59..b5e3320ca50620eafbaf91c985451cf5eadad6fc 100644 (file)
@@ -550,7 +550,6 @@ static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
 
 static const struct header_ops macvlan_hard_header_ops = {
        .create         = macvlan_hard_header,
-       .rebuild        = eth_rebuild_header,
        .parse          = eth_header_parse,
        .cache          = eth_header_cache,
        .cache_update   = eth_header_cache_update,
index 52919ad4272622aeb92d8b9d3d74daf1715a3d40..8f9f3e9fbfce1bdb818b9d4ea5b1c1fa6edc0969 100644 (file)
@@ -798,7 +798,6 @@ static void prism2_tx_timeout(struct net_device *dev)
 
 const struct header_ops hostap_80211_ops = {
        .create         = eth_header,
-       .rebuild        = eth_rebuild_header,
        .cache          = eth_header_cache,
        .cache_update   = eth_header_cache_update,
        .parse          = hostap_80211_header_parse,
index 1d869d185a0dbdb03b33de2b8c0af33c7ea865fa..606563ef8a725e54d27db855c63dad948f3ce815 100644 (file)
@@ -35,7 +35,6 @@ extern const struct header_ops eth_header_ops;
 
 int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
               const void *daddr, const void *saddr, unsigned len);
-int eth_rebuild_header(struct sk_buff *skb);
 int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
 int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
                     __be16 type);
index 5897b4ea5a3f9e0f07f511f57d8fa8bfe7019205..2007f3b44d05ac86d70dde6522db8d673228d73e 100644 (file)
@@ -261,7 +261,6 @@ struct header_ops {
                           unsigned short type, const void *daddr,
                           const void *saddr, unsigned int len);
        int     (*parse)(const struct sk_buff *skb, unsigned char *haddr);
-       int     (*rebuild)(struct sk_buff *skb);
        int     (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type);
        void    (*cache_update)(struct hh_cache *hh,
                                const struct net_device *dev,
@@ -1346,7 +1345,7 @@ enum netdev_priv_flags {
  *                     if one wants to override the ndo_*() functions
  *     @ethtool_ops:   Management operations
  *     @fwd_ops:       Management operations
- *     @header_ops:    Includes callbacks for creating,parsing,rebuilding,etc
+ *     @header_ops:    Includes callbacks for creating,parsing,caching,etc
  *                     of Layer 2 headers.
  *
  *     @flags:         Interface flags (a la BSD)
@@ -2399,15 +2398,6 @@ static inline int dev_parse_header(const struct sk_buff *skb,
        return dev->header_ops->parse(skb, haddr);
 }
 
-static inline int dev_rebuild_header(struct sk_buff *skb)
-{
-       const struct net_device *dev = skb->dev;
-
-       if (!dev->header_ops || !dev->header_ops->rebuild)
-               return 0;
-       return dev->header_ops->rebuild(skb);
-}
-
 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
 int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
 static inline int unregister_gifconf(unsigned int family)
index 73c49864076b3370f015d11616f02c47a2768ff0..21ee1860abbc7109006ebc5d625ac25d41d3f6bc 100644 (file)
@@ -47,7 +47,6 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32
 }
 
 void arp_init(void);
-int arp_find(unsigned char *haddr, struct sk_buff *skb);
 int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
 void arp_send(int type, int ptype, __be32 dest_ip,
              struct net_device *dev, __be32 src_ip,
index bf0396e9a5d3f3c946b30a64c030c9f5c4f17ca0..45feeba7a3250be44e78a1a70b4a7da529a47edf 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
+#include <net/neighbour.h>
 
 #define        AX25_T1CLAMPLO                  1
 #define        AX25_T1CLAMPHI                  (30 * HZ)
@@ -366,10 +367,11 @@ int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *,
                  struct net_device *);
 
 /* ax25_ip.c */
-int ax25_hard_header(struct sk_buff *, struct net_device *, unsigned short,
-                    const void *, const void *, unsigned int);
-int ax25_rebuild_header(struct sk_buff *);
+int ax25_neigh_construct(struct neighbour *neigh);
 extern const struct header_ops ax25_header_ops;
+struct ax25_neigh_priv {
+       struct neigh_ops ops;
+};
 
 /* ax25_out.c */
 ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *,
index 76f708486aaec76031a24ee5ff1d02f126185304..9f912e4d4232d1b5a5ec1ab3f7ef51d0cac730e5 100644 (file)
@@ -193,6 +193,7 @@ struct neigh_table {
        int                     family;
        int                     entry_size;
        int                     key_len;
+       __be16                  protocol;
        __u32                   (*hash)(const void *pkey,
                                        const struct net_device *dev,
                                        __u32 *hash_rnd);
@@ -268,7 +269,6 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
 int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
-int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
 int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
 struct neighbour *neigh_event_ns(struct neigh_table *tbl,
                                                u8 *lladdr, void *saddr,
index 7c174b6750cd654c49d7c1d2f621eb9fc3ed1ef0..7b9219022418b2e5a4686b9504f42e32cd091128 100644 (file)
@@ -75,29 +75,8 @@ static int fc_header(struct sk_buff *skb, struct net_device *dev,
        return -hdr_len;
 }
 
-/*
- *     A neighbour discovery of some species (eg arp) has completed. We
- *     can now send the packet.
- */
-
-static int fc_rebuild_header(struct sk_buff *skb)
-{
-#ifdef CONFIG_INET
-       struct fch_hdr *fch=(struct fch_hdr *)skb->data;
-       struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr));
-       if(fcllc->ethertype != htons(ETH_P_IP)) {
-               printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(fcllc->ethertype));
-               return 0;
-       }
-       return arp_find(fch->daddr, skb);
-#else
-       return 0;
-#endif
-}
-
 static const struct header_ops fc_header_ops = {
        .create  = fc_header,
-       .rebuild = fc_rebuild_header,
 };
 
 static void fc_setup(struct net_device *dev)
index 59e7346f1193a612f9118b4df85426406aea5549..7d3a0af954e8f7b2eeb1a38dd98a60ce3c230aed 100644 (file)
@@ -87,31 +87,6 @@ static int fddi_header(struct sk_buff *skb, struct net_device *dev,
        return -hl;
 }
 
-
-/*
- * Rebuild the FDDI MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on
- * this sk_buff.  We now let ARP fill in the other fields.
- */
-
-static int fddi_rebuild_header(struct sk_buff  *skb)
-{
-       struct fddihdr *fddi = (struct fddihdr *)skb->data;
-
-#ifdef CONFIG_INET
-       if (fddi->hdr.llc_snap.ethertype == htons(ETH_P_IP))
-               /* Try to get ARP to resolve the header and fill destination address */
-               return arp_find(fddi->daddr, skb);
-       else
-#endif
-       {
-               printk("%s: Don't know how to resolve type %04X addresses.\n",
-                      skb->dev->name, ntohs(fddi->hdr.llc_snap.ethertype));
-               return 0;
-       }
-}
-
-
 /*
  * Determine the packet's protocol ID and fill in skb fields.
  * This routine is called before an incoming packet is passed
@@ -177,7 +152,6 @@ EXPORT_SYMBOL(fddi_change_mtu);
 
 static const struct header_ops fddi_header_ops = {
        .create         = fddi_header,
-       .rebuild        = fddi_rebuild_header,
 };
 
 
index 2e03f8259dd55a575f1b147987631cdced3a91a9..ade1a52cdcff8e6a690b38bde8d7af1c140d7d9c 100644 (file)
@@ -90,33 +90,6 @@ static int hippi_header(struct sk_buff *skb, struct net_device *dev,
 }
 
 
-/*
- * Rebuild the HIPPI MAC header. This is called after an ARP has
- * completed on this sk_buff. We now let ARP fill in the other fields.
- */
-
-static int hippi_rebuild_header(struct sk_buff *skb)
-{
-       struct hippi_hdr *hip = (struct hippi_hdr *)skb->data;
-
-       /*
-        * Only IP is currently supported
-        */
-
-       if(hip->snap.ethertype != htons(ETH_P_IP))
-       {
-               printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype));
-               return 0;
-       }
-
-       /*
-        * We don't support dynamic ARP on HIPPI, but we use the ARP
-        * static ARP tables to hold the I-FIELDs.
-        */
-       return arp_find(hip->le.daddr, skb);
-}
-
-
 /*
  *     Determine the packet's protocol ID.
  */
@@ -186,7 +159,6 @@ EXPORT_SYMBOL(hippi_neigh_setup_dev);
 
 static const struct header_ops hippi_header_ops = {
        .create         = hippi_header,
-       .rebuild        = hippi_rebuild_header,
 };
 
 
index 118956448cf6e4aa9a3609ccf7455a04596e24bf..1dcfec8b49f3f4a725b853f8ce9ee202bab5c7f1 100644 (file)
 #include <linux/if_vlan.h>
 #include <linux/netpoll.h>
 
-/*
- *     Rebuild the Ethernet MAC header. This is called after an ARP
- *     (or in future other address resolution) has completed on this
- *     sk_buff. We now let ARP fill in the other fields.
- *
- *     This routine CANNOT use cached dst->neigh!
- *     Really, it is used only when dst->neigh is wrong.
- *
- * TODO:  This needs a checkup, I'm ignorant here. --BLG
- */
-static int vlan_dev_rebuild_header(struct sk_buff *skb)
-{
-       struct net_device *dev = skb->dev;
-       struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data);
-
-       switch (veth->h_vlan_encapsulated_proto) {
-#ifdef CONFIG_INET
-       case htons(ETH_P_IP):
-
-               /* TODO:  Confirm this will work with VLAN headers... */
-               return arp_find(veth->h_dest, skb);
-#endif
-       default:
-               pr_debug("%s: unable to resolve type %X addresses\n",
-                        dev->name, ntohs(veth->h_vlan_encapsulated_proto));
-
-               ether_addr_copy(veth->h_source, dev->dev_addr);
-               break;
-       }
-
-       return 0;
-}
-
 /*
  *     Create the VLAN header for an arbitrary protocol layer
  *
@@ -534,7 +501,6 @@ static int vlan_dev_get_lock_subclass(struct net_device *dev)
 
 static const struct header_ops vlan_header_ops = {
        .create  = vlan_dev_hard_header,
-       .rebuild = vlan_dev_rebuild_header,
        .parse   = eth_header_parse,
 };
 
@@ -554,7 +520,6 @@ static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev
 
 static const struct header_ops vlan_passthru_header_ops = {
        .create  = vlan_passthru_hard_header,
-       .rebuild = dev_rebuild_header,
        .parse   = eth_header_parse,
 };
 
index 67de6b33f2c309ad4426b2075b1bd16d8ce27e11..e030c64ebfb77bfc41ca6edf6b3211b1765485ff 100644 (file)
@@ -46,9 +46,9 @@
 
 #ifdef CONFIG_INET
 
-int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
-                    unsigned short type, const void *daddr,
-                    const void *saddr, unsigned int len)
+static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
+                           unsigned short type, const void *daddr,
+                           const void *saddr, unsigned int len)
 {
        unsigned char *buff;
 
@@ -100,7 +100,7 @@ int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
        return -AX25_HEADER_LEN;        /* Unfinished header */
 }
 
-int ax25_rebuild_header(struct sk_buff *skb)
+static int ax25_neigh_xmit(struct sk_buff *skb)
 {
        struct sk_buff *ourskb;
        unsigned char *bp  = skb->data;
@@ -115,9 +115,6 @@ int ax25_rebuild_header(struct sk_buff *skb)
        dst = (ax25_address *)(bp + 1);
        src = (ax25_address *)(bp + 8);
 
-       if (arp_find(bp + 1, skb))
-               return 1;
-
        route = ax25_get_route(dst, NULL);
        if (route) {
                digipeat = route->digipeat;
@@ -129,6 +126,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
                dev = skb->dev;
 
        if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
+               kfree_skb(skb);
                goto put;
        }
 
@@ -215,28 +213,74 @@ put:
        return 1;
 }
 
+static int ax25_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
+{
+       /* Except for calling ax25_neigh_xmit instead of
+        * dev_queue_xmit this is neigh_resolve_output.
+        */
+       int rc = 0;
+
+       if (!neigh_event_send(neigh, skb)) {
+               int err;
+               struct net_device *dev = neigh->dev;
+               unsigned int seq;
+
+               do {
+                       __skb_pull(skb, skb_network_offset(skb));
+                       seq = read_seqbegin(&neigh->ha_lock);
+                       err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+                                             neigh->ha, NULL, skb->len);
+               } while (read_seqretry(&neigh->ha_lock, seq));
+
+               if (err >= 0) {
+                       ax25_neigh_xmit(skb);
+               } else
+                       goto out_kfree_skb;
+       }
+out:
+       return rc;
+
+out_kfree_skb:
+       rc = -EINVAL;
+       kfree_skb(skb);
+       goto out;
+}
+
+int ax25_neigh_construct(struct neighbour *neigh)
+{
+       /* This trouble could be saved if ax25 would right a proper
+        * dev_queue_xmit function.
+        */
+       struct ax25_neigh_priv *priv = neighbour_priv(neigh);
+
+       if (neigh->tbl->family != AF_INET)
+               return -EINVAL;
+
+       priv->ops = *neigh->ops;
+       priv->ops.output = ax25_neigh_output;
+       priv->ops.connected_output = ax25_neigh_output;
+       return 0;
+}
+
 #else  /* INET */
 
-int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
-                    unsigned short type, const void *daddr,
-                    const void *saddr, unsigned int len)
+static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
+                           unsigned short type, const void *daddr,
+                           const void *saddr, unsigned int len)
 {
        return -AX25_HEADER_LEN;
 }
 
-int ax25_rebuild_header(struct sk_buff *skb)
+int ax25_neigh_construct(struct neighbour *neigh)
 {
-       return 1;
+       return 0;
 }
-
 #endif
 
 const struct header_ops ax25_header_ops = {
        .create = ax25_hard_header,
-       .rebuild = ax25_rebuild_header,
 };
 
-EXPORT_SYMBOL(ax25_hard_header);
-EXPORT_SYMBOL(ax25_rebuild_header);
 EXPORT_SYMBOL(ax25_header_ops);
+EXPORT_SYMBOL(ax25_neigh_construct);
 
index 70fe9e10ac867f495086810dc6ea619f69d59368..0f48ea3affed3f53871a2ab01972b32a01c6ed31 100644 (file)
@@ -1263,10 +1263,10 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
 EXPORT_SYMBOL(neigh_event_ns);
 
 /* called with read_lock_bh(&n->lock); */
-static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
+static void neigh_hh_init(struct neighbour *n)
 {
-       struct net_device *dev = dst->dev;
-       __be16 prot = dst->ops->protocol;
+       struct net_device *dev = n->dev;
+       __be16 prot = n->tbl->protocol;
        struct hh_cache *hh = &n->hh;
 
        write_lock_bh(&n->lock);
@@ -1280,43 +1280,19 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
        write_unlock_bh(&n->lock);
 }
 
-/* This function can be used in contexts, where only old dev_queue_xmit
- * worked, f.e. if you want to override normal output path (eql, shaper),
- * but resolution is not made yet.
- */
-
-int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
-{
-       struct net_device *dev = skb->dev;
-
-       __skb_pull(skb, skb_network_offset(skb));
-
-       if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
-                           skb->len) < 0 &&
-           dev_rebuild_header(skb))
-               return 0;
-
-       return dev_queue_xmit(skb);
-}
-EXPORT_SYMBOL(neigh_compat_output);
-
 /* Slow and careful. */
 
 int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
 {
-       struct dst_entry *dst = skb_dst(skb);
        int rc = 0;
 
-       if (!dst)
-               goto discard;
-
        if (!neigh_event_send(neigh, skb)) {
                int err;
                struct net_device *dev = neigh->dev;
                unsigned int seq;
 
                if (dev->header_ops->cache && !neigh->hh.hh_len)
-                       neigh_hh_init(neigh, dst);
+                       neigh_hh_init(neigh);
 
                do {
                        __skb_pull(skb, skb_network_offset(skb));
@@ -1332,8 +1308,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
        }
 out:
        return rc;
-discard:
-       neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
 out_kfree_skb:
        rc = -EINVAL;
        kfree_skb(skb);
index 7ca7c3143da332d567bd336197beff18ce210083..f123c6c6748c10b98e7e7500c108936dc634a128 100644 (file)
@@ -97,6 +97,7 @@ struct neigh_table dn_neigh_table = {
        .family =                       PF_DECnet,
        .entry_size =                   NEIGH_ENTRY_SIZE(sizeof(struct dn_neigh)),
        .key_len =                      sizeof(__le16),
+       .protocol =                     cpu_to_be16(ETH_P_DNA_RT),
        .hash =                         dn_neigh_hash,
        .constructor =                  dn_neigh_construct,
        .id =                           "dn_neigh_cache",
index 238f38d21641fb16071caacd90f15dcb07815a25..8dbdf6c910b7e5ba44827000e70e6bf15e97a1ce 100644 (file)
@@ -112,39 +112,6 @@ int eth_header(struct sk_buff *skb, struct net_device *dev,
 }
 EXPORT_SYMBOL(eth_header);
 
-/**
- * eth_rebuild_header- rebuild the Ethernet MAC header.
- * @skb: socket buffer to update
- *
- * This is called after an ARP or IPV6 ndisc it's resolution on this
- * sk_buff. We now let protocol (ARP) fill in the other fields.
- *
- * This routine CANNOT use cached dst->neigh!
- * Really, it is used only when dst->neigh is wrong.
- */
-int eth_rebuild_header(struct sk_buff *skb)
-{
-       struct ethhdr *eth = (struct ethhdr *)skb->data;
-       struct net_device *dev = skb->dev;
-
-       switch (eth->h_proto) {
-#ifdef CONFIG_INET
-       case htons(ETH_P_IP):
-               return arp_find(eth->h_dest, skb);
-#endif
-       default:
-               netdev_dbg(dev,
-                      "%s: unable to resolve type %X addresses.\n",
-                      dev->name, ntohs(eth->h_proto));
-
-               memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
-               break;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(eth_rebuild_header);
-
 /**
  * eth_get_headlen - determine the the length of header for an ethernet frame
  * @data: pointer to start of frame
@@ -369,7 +336,6 @@ EXPORT_SYMBOL(eth_validate_addr);
 const struct header_ops eth_header_ops ____cacheline_aligned = {
        .create         = eth_header,
        .parse          = eth_header_parse,
-       .rebuild        = eth_rebuild_header,
        .cache          = eth_header_cache,
        .cache_update   = eth_header_cache_update,
 };
index 205e1472aa7819784091d588818e1ab602f6006f..6b8aad6a0d7dd2b28c6d52d16b3357136a73241b 100644 (file)
@@ -149,17 +149,10 @@ static const struct neigh_ops arp_direct_ops = {
        .connected_output =     neigh_direct_output,
 };
 
-static const struct neigh_ops arp_broken_ops = {
-       .family =               AF_INET,
-       .solicit =              arp_solicit,
-       .error_report =         arp_error_report,
-       .output =               neigh_compat_output,
-       .connected_output =     neigh_compat_output,
-};
-
 struct neigh_table arp_tbl = {
        .family         = AF_INET,
        .key_len        = 4,
+       .protocol       = cpu_to_be16(ETH_P_IP),
        .hash           = arp_hash,
        .constructor    = arp_constructor,
        .proxy_redo     = parp_redo,
@@ -260,35 +253,6 @@ static int arp_constructor(struct neighbour *neigh)
                   in old paradigm.
                 */
 
-#if 1
-               /* So... these "amateur" devices are hopeless.
-                  The only thing, that I can say now:
-                  It is very sad that we need to keep ugly obsolete
-                  code to make them happy.
-
-                  They should be moved to more reasonable state, now
-                  they use rebuild_header INSTEAD OF hard_start_xmit!!!
-                  Besides that, they are sort of out of date
-                  (a lot of redundant clones/copies, useless in 2.1),
-                  I wonder why people believe that they work.
-                */
-               switch (dev->type) {
-               default:
-                       break;
-               case ARPHRD_ROSE:
-#if IS_ENABLED(CONFIG_AX25)
-               case ARPHRD_AX25:
-#if IS_ENABLED(CONFIG_NETROM)
-               case ARPHRD_NETROM:
-#endif
-                       neigh->ops = &arp_broken_ops;
-                       neigh->output = neigh->ops->output;
-                       return 0;
-#else
-                       break;
-#endif
-               }
-#endif
                if (neigh->type == RTN_MULTICAST) {
                        neigh->nud_state = NUD_NOARP;
                        arp_mc_map(addr, neigh->ha, dev, 1);
@@ -433,71 +397,6 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
        return flag;
 }
 
-/* OBSOLETE FUNCTIONS */
-
-/*
- *     Find an arp mapping in the cache. If not found, post a request.
- *
- *     It is very UGLY routine: it DOES NOT use skb->dst->neighbour,
- *     even if it exists. It is supposed that skb->dev was mangled
- *     by a virtual device (eql, shaper). Nobody but broken devices
- *     is allowed to use this function, it is scheduled to be removed. --ANK
- */
-
-static int arp_set_predefined(int addr_hint, unsigned char *haddr,
-                             __be32 paddr, struct net_device *dev)
-{
-       switch (addr_hint) {
-       case RTN_LOCAL:
-               pr_debug("arp called for own IP address\n");
-               memcpy(haddr, dev->dev_addr, dev->addr_len);
-               return 1;
-       case RTN_MULTICAST:
-               arp_mc_map(paddr, haddr, dev, 1);
-               return 1;
-       case RTN_BROADCAST:
-               memcpy(haddr, dev->broadcast, dev->addr_len);
-               return 1;
-       }
-       return 0;
-}
-
-
-int arp_find(unsigned char *haddr, struct sk_buff *skb)
-{
-       struct net_device *dev = skb->dev;
-       __be32 paddr;
-       struct neighbour *n;
-
-       if (!skb_dst(skb)) {
-               pr_debug("arp_find is called with dst==NULL\n");
-               kfree_skb(skb);
-               return 1;
-       }
-
-       paddr = rt_nexthop(skb_rtable(skb), ip_hdr(skb)->daddr);
-       if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr,
-                              paddr, dev))
-               return 0;
-
-       n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
-
-       if (n) {
-               n->used = jiffies;
-               if (n->nud_state & NUD_VALID || neigh_event_send(n, skb) == 0) {
-                       neigh_ha_snapshot(haddr, n, dev);
-                       neigh_release(n);
-                       return 0;
-               }
-               neigh_release(n);
-       } else
-               kfree_skb(skb);
-       return 1;
-}
-EXPORT_SYMBOL(arp_find);
-
-/* END OF OBSOLETE FUNCTIONS */
-
 /*
  * Check if we can use proxy ARP for this path
  */
index 471ed24aabaec4b1d8736438696ca3490d4e0f58..e363bbc2420d8dec7e4d3c4626ac089513d0a04e 100644 (file)
@@ -117,6 +117,7 @@ static const struct neigh_ops ndisc_direct_ops = {
 struct neigh_table nd_tbl = {
        .family =       AF_INET6,
        .key_len =      sizeof(struct in6_addr),
+       .protocol =     cpu_to_be16(ETH_P_IPV6),
        .hash =         ndisc_hash,
        .constructor =  ndisc_constructor,
        .pconstructor = pndisc_constructor,
index 6ae063cebf7de71082f0b526ecbfcd935f70dff4..988f542481a835c394549666d5244be8b48e9faa 100644 (file)
@@ -65,36 +65,6 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
        return 1;
 }
 
-#ifdef CONFIG_INET
-
-static int nr_rebuild_header(struct sk_buff *skb)
-{
-       unsigned char *bp = skb->data;
-
-       if (arp_find(bp + 7, skb))
-               return 1;
-
-       bp[6] &= ~AX25_CBIT;
-       bp[6] &= ~AX25_EBIT;
-       bp[6] |= AX25_SSSID_SPARE;
-       bp    += AX25_ADDR_LEN;
-
-       bp[6] &= ~AX25_CBIT;
-       bp[6] |= AX25_EBIT;
-       bp[6] |= AX25_SSSID_SPARE;
-
-       return 0;
-}
-
-#else
-
-static int nr_rebuild_header(struct sk_buff *skb)
-{
-       return 1;
-}
-
-#endif
-
 static int nr_header(struct sk_buff *skb, struct net_device *dev,
                     unsigned short type,
                     const void *daddr, const void *saddr, unsigned int len)
@@ -188,7 +158,6 @@ static netdev_tx_t nr_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static const struct header_ops nr_header_ops = {
        .create = nr_header,
-       .rebuild= nr_rebuild_header,
 };
 
 static const struct net_device_ops nr_netdev_ops = {
index 50005888be573245fc1d30b8f38bc90b10c89698..369ca81a8c5dd262539f686c6d1d5700c8e07971 100644 (file)
@@ -41,6 +41,9 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev,
 {
        unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2);
 
+       if (daddr)
+               memcpy(buff + 7, daddr, dev->addr_len);
+
        *buff++ = ROSE_GFI | ROSE_Q_BIT;
        *buff++ = 0x00;
        *buff++ = ROSE_DATA;
@@ -53,43 +56,6 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev,
        return -37;
 }
 
-static int rose_rebuild_header(struct sk_buff *skb)
-{
-#ifdef CONFIG_INET
-       struct net_device *dev = skb->dev;
-       struct net_device_stats *stats = &dev->stats;
-       unsigned char *bp = (unsigned char *)skb->data;
-       struct sk_buff *skbn;
-       unsigned int len;
-
-       if (arp_find(bp + 7, skb)) {
-               return 1;
-       }
-
-       if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-               kfree_skb(skb);
-               return 1;
-       }
-
-       if (skb->sk != NULL)
-               skb_set_owner_w(skbn, skb->sk);
-
-       kfree_skb(skb);
-
-       len = skbn->len;
-
-       if (!rose_route_frame(skbn, NULL)) {
-               kfree_skb(skbn);
-               stats->tx_errors++;
-               return 1;
-       }
-
-       stats->tx_packets++;
-       stats->tx_bytes += len;
-#endif
-       return 1;
-}
-
 static int rose_set_mac_address(struct net_device *dev, void *addr)
 {
        struct sockaddr *sa = addr;
@@ -134,19 +100,26 @@ static int rose_close(struct net_device *dev)
 static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_device_stats *stats = &dev->stats;
+       unsigned int len = skb->len;
 
        if (!netif_running(dev)) {
                printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
                return NETDEV_TX_BUSY;
        }
-       dev_kfree_skb(skb);
-       stats->tx_errors++;
+
+       if (!rose_route_frame(skb, NULL)) {
+               dev_kfree_skb(skb);
+               stats->tx_errors++;
+               return NETDEV_TX_OK;
+       }
+
+       stats->tx_packets++;
+       stats->tx_bytes += len;
        return NETDEV_TX_OK;
 }
 
 static const struct header_ops rose_header_ops = {
        .create = rose_header,
-       .rebuild = rose_rebuild_header,
 };
 
 static const struct net_device_ops rose_netdev_ops = {
This page took 0.047981 seconds and 5 git commands to generate.