提交 b898441f 编写于 作者: D David S. Miller

Merge branch 'neigh_cleanups'

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: NDavid S. Miller <davem@davemloft.net>
......@@ -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,
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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)
......
......@@ -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 */
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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)
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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);
......
......@@ -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)
......
......@@ -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,
......
......@@ -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 *,
......
......@@ -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,
......
......@@ -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)
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -36,39 +36,6 @@
#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,
};
......
......@@ -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 @@ int ax25_rebuild_header(struct sk_buff *skb)
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);
......@@ -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);
......
......@@ -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",
......
......@@ -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,
};
......
......@@ -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
*/
......
......@@ -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,
......
......@@ -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 = {
......
......@@ -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 = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册