Removing duplicate code.
Signed-off-by: Linus Lüssing linus.luessing@c0d3.blue --- Changes in RFC -> non-RFC: * Added kerneldoc * Added Signed-off-by
net/batman-adv/distributed-arp-table.c | 61 ++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 21 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index fa76465..66114af 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -948,6 +948,41 @@ static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size) }
/** + * batadv_dat_arp_create_reply - create an ARP Reply + * @bat_priv: the bat priv with all the soft interface information + * @ip_src: ARP sender IP + * @ip_dst: ARP target IP + * @hw_src: Ethernet source and ARP sender MAC + * @hw_dst: Ethernet destination and ARP target MAC + * @vid: VLAN identifier (optional, set to zero otherwise) + * + * Creates an ARP Reply from the given values, optionally encapsulated in a + * VLAN header. + * + * Return: An skb containing an ARP Reply. + */ +static struct sk_buff * +batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src, + __be32 ip_dst, u8 *hw_src, u8 *hw_dst, + unsigned short vid) +{ + struct sk_buff *skb; + + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_dst, bat_priv->soft_iface, + ip_src, hw_dst, hw_src, hw_dst); + if (!skb) + return NULL; + + if (vid & BATADV_VLAN_HAS_TAG) + skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), + vid & VLAN_VID_MASK); + + skb_reset_mac_header(skb); + + return skb; +} + +/** * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to * answer using DAT * @bat_priv: the bat priv with all the soft interface information @@ -1005,17 +1040,12 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, goto out; }
- skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, - bat_priv->soft_iface, ip_dst, hw_src, - dat_entry->mac_addr, hw_src); + skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src, + dat_entry->mac_addr, + hw_src, vid); if (!skb_new) goto out;
- if (vid & BATADV_VLAN_HAS_TAG) - skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q), - vid & VLAN_VID_MASK); - - skb_reset_mac_header(skb_new); skb_new->protocol = eth_type_trans(skb_new, bat_priv->soft_iface); bat_priv->stats.rx_packets++; @@ -1079,22 +1109,11 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, if (!dat_entry) goto out;
- skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, - bat_priv->soft_iface, ip_dst, hw_src, - dat_entry->mac_addr, hw_src); - + skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src, + dat_entry->mac_addr, hw_src, vid); if (!skb_new) goto out;
- /* the rest of the TX path assumes that the mac_header offset pointing - * to the inner Ethernet header has been set, therefore reset it now. - */ - skb_reset_mac_header(skb_new); - - if (vid & BATADV_VLAN_HAS_TAG) - skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q), - vid & VLAN_VID_MASK); - /* To preserve backwards compatibility, the node has choose the outgoing * format based on the incoming request packet type. The assumption is * that a node not using the 4addr packet format doesn't support it.
In a typical mesh network, when a new client connects then it will usually first try to grab an IPv4 address via DHCP. Afterwards in public mesh networks a client will try to contact the internet over the server.
While the IPv4 address of the DHCP-Server is usually well propagated in the DHT, the IPv4 address of a newly joining client is not.
This can lead to a considerable amount of ARP broadcasts not caught by DAT from the servers.
In a 1000 nodes mesh network (Freifunk Hamburg) we can still see 30KBit/s of ARP traffic (equalling about 25% of all layer two specific overhead, remaining after some filtering) flooded through the mesh. These 30KBit/s are mainly ARP Requests from the gateways / DHCP servers.
Through snooping DHCPACKs we can actually learn about MAC/IP address pairs without the need of any flooded ARP messages in advance. This allows servers to fill their local DAT cache with according entries before any communciation with a client can possibly have taken place.
Signed-off-by: Linus Lüssing linus.luessing@c0d3.blue ---
Changes in RFC -> non-RFC
* Added kerneldoc * Added Signed-off-by * More IP Header checks (iph->hlen considered, ip version checked, ...) * Parsing & checking DHCP Message Type Option, only snooping DHCPACKs now * Moved ethernet protocol check from batadv_dat_check_dhcp to batadv_dat_check_dhcp_ipudp * Removed buffer-length parameter from batadv_dat_dhcp_get_{yiaddr,chaddr}() * Renamed batadv_dat_put() to batadv_dat_put_pairs()
net/batman-adv/distributed-arp-table.c | 297 +++++++++++++++++++++++++++++++++ net/batman-adv/distributed-arp-table.h | 4 + net/batman-adv/packet.h | 48 ++++++ net/batman-adv/soft-interface.c | 11 +- 4 files changed, 358 insertions(+), 2 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 66114af..3a66d4b 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -28,6 +28,7 @@ #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/in.h> +#include <linux/ip.h> #include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/kref.h> @@ -40,8 +41,10 @@ #include <linux/spinlock.h> #include <linux/stddef.h> #include <linux/string.h> +#include <linux/udp.h> #include <linux/workqueue.h> #include <net/arp.h> +#include <net/ip.h>
#include "hard-interface.h" #include "hash.h" @@ -973,6 +976,8 @@ batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src, if (!skb) return NULL;
+ skb_set_network_header(skb, ETH_HLEN); + if (vid & BATADV_VLAN_HAS_TAG) skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), vid & VLAN_VID_MASK); @@ -1237,6 +1242,298 @@ out: }
/** + * batadv_dat_check_dhcp_ipudp - check skb for IP+UDP headers valid for DHCP + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * + * Checks whether the given skb has an IP and UDP header valid for a DHCP + * message from a DHCP server. + * + * Return: True if valid, false otherwise. + */ +static bool batadv_dat_check_dhcp_ipudp(struct sk_buff *skb) +{ + struct iphdr *iphdr, _iphdr; + struct udphdr *udphdr, _udphdr; + unsigned int offset = skb_network_offset(skb); + + iphdr = skb_header_pointer(skb, offset, sizeof(_iphdr), &_iphdr); + if (!iphdr || iphdr->version != 4 || ip_hdrlen(skb) < sizeof(_iphdr)) + return false; + + if (iphdr->protocol != IPPROTO_UDP) + return false; + + offset += ip_hdrlen(skb); + skb_set_transport_header(skb, offset); + + udphdr = skb_header_pointer(skb, offset, sizeof(_udphdr), &_udphdr); + if (!udphdr || udphdr->source != htons(67)) + return false; + + return true; +} + +/** + * batadv_dat_check_dhcp - examine packet for valid DHCP message + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * + * Checks whether the given skb is a valid DHCP packet. + * + * Caller needs to ensure that the skb network header is set correctly. + * + * Return: If skb is a valid DHCP packet, then returns its op code + * (e.g. BOOTREPLY vs. BOOTREQUEST). Otherwise returns -EINVAL. + */ +static int batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto) +{ + u8 *op, _op; + u8 *htype, _htype; + u8 *hlen, _hlen; + __be32 *magic, _magic; + unsigned int dhcp_offset; + unsigned int offset; + + if (proto != htons(ETH_P_IP)) + return -EINVAL; + + if (!batadv_dat_check_dhcp_ipudp(skb)) + return -EINVAL; + + dhcp_offset = skb_transport_offset(skb) + sizeof(struct udphdr); + if (skb->len < dhcp_offset + sizeof(struct batadv_dhcp_packet)) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, op); + + op = skb_header_pointer(skb, offset, sizeof(_op), &_op); + if (!op) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, htype); + + htype = skb_header_pointer(skb, offset, sizeof(_htype), &_htype); + if (!htype || *htype != BATADV_HTYPE_ETHERNET) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, hlen); + + hlen = skb_header_pointer(skb, offset, sizeof(_hlen), &_hlen); + if (!hlen || *hlen != ETH_ALEN) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, magic); + + magic = skb_header_pointer(skb, offset, sizeof(_magic), &_magic); + if (!magic || *magic != htonl(BATADV_DHCP_MAGIC)) + return -EINVAL; + + return *op; +} + +/** + * batadv_dat_get_dhcp_message_type - get message type of a DHCP packet + * @skb: the DHCP packet to parse + * + * Iterates over the DHCP options of the given DHCP packet to find a + * DHCP Message Type option and parse it. + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: The found DHCP message type value, if found. -EINVAL otherwise. + */ +static int batadv_dat_get_dhcp_message_type(struct sk_buff *skb) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + u8 *type, _type; + struct { + u8 type; + u8 len; + } *tl, _tl; + + offset += sizeof(struct batadv_dhcp_packet); + + while ((tl = skb_header_pointer(skb, offset, sizeof(_tl), &_tl))) { + if (tl->type == BATADV_DHCP_OPT_MSG_TYPE) + break; + + if (tl->type == BATADV_DHCP_OPT_END) + break; + + if (tl->type == BATADV_DHCP_OPT_PAD) + offset++; + else + offset += tl->len + sizeof(_tl); + } + + /* Option Overload Code not supported */ + if (!tl || tl->type != BATADV_DHCP_OPT_MSG_TYPE || + tl->len != sizeof(_type)) + return -EINVAL; + + offset += sizeof(_tl); + + type = skb_header_pointer(skb, offset, sizeof(_type), &_type); + if (!type) + return -EINVAL; + + return *type; +} + +/** + * batadv_dat_get_dhcp_yiaddr - get yiaddr from a DHCP packet + * @skb: the DHCP packet to parse + * @buffer: a buffer to store the yiaddr in (if necessary / skb is non-linear) + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: A safely accessible "Your IP Address" field from the provided DHCP + * packet. + */ +static __be32 *batadv_dat_dhcp_get_yiaddr(struct sk_buff *skb, __be32 *buffer) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + unsigned int len = sizeof(((struct batadv_dhcp_packet *)0)->yiaddr); + + offset += offsetof(struct batadv_dhcp_packet, yiaddr); + + return skb_header_pointer(skb, offset, len, buffer); +} + +/** + * batadv_dat_get_dhcp_chaddr - get chaddr from a DHCP packet + * @skb: the DHCP packet to parse + * @buffer: a buffer to store the chaddr in (if necessary / skb is non-linear) + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: A safely accessible "Client Hardware Address" field from the provided + * DHCP packet. + */ +static u8 *batadv_dat_get_dhcp_chaddr(struct sk_buff *skb, u8 *buffer) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + unsigned int len = sizeof(((struct batadv_dhcp_packet *)0)->chaddr); + + offset += offsetof(struct batadv_dhcp_packet, chaddr); + + return skb_header_pointer(skb, offset, len, buffer); +} + +/** + * batadv_dat_put_pairs - puts two MAC/IP pairs into the DHT and DAT cache + * @bat_priv: the bat priv with all the soft interface information + * @hw_src: first value of DHT and ARP sender MAC + * @ip_src: first key of DHT and ARP sender IP + * @hw_dst: second value of DHT and ARP target MAC + * @ip_dst: second key of DHT and ARP target IP + * @vid: VLAN identifier + * + * First checks whether the given MAC/IP pairs are suitable for DAT. If so, adds + * them to the local DAT cache and propagates them further into the DHT. + * + * For the DHT propagation, hw_src/ip_src will appear as the ARP Reply + * transmitter (and hw_dst/ip_dst as the target). + * + * Return: True on success, false otherwise. + */ +static bool batadv_dat_put_pairs(struct batadv_priv *bat_priv, u8 *hw_src, + __be32 ip_src, u8 *hw_dst, __be32 ip_dst, + unsigned short vid) +{ + struct sk_buff *skb; + int hdr_size; + u16 type; + int ret = false; + + skb = batadv_dat_arp_create_reply(bat_priv, ip_src, ip_dst, hw_src, + hw_dst, vid); + if (!skb) + return false; + + /* Check for validity of provided addresses */ + hdr_size = skb_network_offset(skb) - ETH_HLEN; + type = batadv_arp_get_type(bat_priv, skb, hdr_size); + if (type != ARPOP_REPLY) + goto err_skip_commit; + + batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid); + batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid); + + batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT); + batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT); + + ret = true; + +err_skip_commit: + dev_kfree_skb(skb); + return ret; +} + +/** + * batadv_dat_snoop_outgoing_dhcp_ack - snoop DHCPACK and fill DAT with it + * @bat_priv: the bat priv with all the soft interface information + * @skb: the packet to snoop + * @proto: ethernet protocol hint (behind a potential vlan) + * @vid: VLAN identifier + * + * This function first checks whether the given skb is a valid DHCPACK. If + * so then its source MAC and IP as well as its DHCP Client Hardware Address + * field and DHCP Your IP Address field are added to the local DAT cache and + * propagated into the DHT. + * + * Caller needs to ensure that the skb mac and network headers are set + * correctly. + */ +void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, + __be16 proto, + unsigned short vid) +{ + int type; + u8 *chaddr, _chaddr[ETH_ALEN]; + __be32 *yiaddr, _yiaddr; + + if (!atomic_read(&bat_priv->distributed_arp_table)) + return; + + if (batadv_dat_check_dhcp(skb, proto) != BATADV_BOOTREPLY) + return; + + type = batadv_dat_get_dhcp_message_type(skb); + if (type != BATADV_DHCPACK) + return; + + yiaddr = batadv_dat_dhcp_get_yiaddr(skb, &_yiaddr); + if (!yiaddr) + return; + + chaddr = batadv_dat_get_dhcp_chaddr(skb, _chaddr); + if (!chaddr) + return; + + /* ARP sender MAC + IP -> DHCP Client (chaddr+yiaddr), + * ARP target MAC + IP -> DHCP Server (ethhdr/iphdr sources) + */ + if (!batadv_dat_put_pairs(bat_priv, chaddr, *yiaddr, + eth_hdr(skb)->h_source, ip_hdr(skb)->saddr, + vid)) + return; + + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from DHCPACK (server-side): %pI4, %pM (vid: %i)\n", + &ip_hdr(skb)->saddr, eth_hdr(skb)->h_source, + BATADV_PRINT_VID(vid)); + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from DHCPACK (client-side): %pI4, %pM (vid: %i)\n", + yiaddr, chaddr, BATADV_PRINT_VID(vid)); +} + +/** * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped * (because the node has already obtained the reply via DAT) or not * @bat_priv: the bat priv with all the soft interface information diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index 813ecea..c81234c 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h @@ -44,6 +44,10 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, struct sk_buff *skb); bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size); +void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, + __be16 proto, + unsigned short vid); bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet);
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 6b011ff..d8afbfa 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -664,4 +664,52 @@ struct batadv_tvlv_mcast_data { u8 reserved[3]; };
+enum batadv_bootpop { + BATADV_BOOTREQUEST = 1, + BATADV_BOOTREPLY = 2, +}; + +enum batadv_boothtype { + BATADV_HTYPE_ETHERNET = 1, +}; + +enum batadv_dhcpoptioncode { + BATADV_DHCP_OPT_PAD = 0, + BATADV_DHCP_OPT_MSG_TYPE = 53, + BATADV_DHCP_OPT_END = 255, +}; + +enum batadv_dhcptype { + BATADV_DHCPDISCOVER = 1, + BATADV_DHCPOFFER = 2, + BATADV_DHCPREQUEST = 3, + BATADV_DHCPDECLINE = 4, + BATADV_DHCPACK = 5, + BATADV_DHCPNAK = 6, + BATADV_DHCPRELEASE = 7, + BATADV_DHCPINFORM = 8, +}; + +/* { 99, 130, 83, 99 } */ +#define BATADV_DHCP_MAGIC 1669485411 + +struct batadv_dhcp_packet { + u8 op; + u8 htype; + u8 hlen; + u8 hops; + __be32 xid; + __be16 secs; + __be16 flags; + __be32 ciaddr; + __be32 yiaddr; + __be32 siaddr; + __be32 giaddr; + u8 chaddr[16]; + u8 sname[64]; + u8 file[128]; + __be32 magic; + u8 options[0]; +}; + #endif /* _NET_BATMAN_ADV_PACKET_H_ */ diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 216ac03..12bc41b 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -204,6 +204,7 @@ static int batadv_interface_tx(struct sk_buff *skb, enum batadv_forw_mode forw_mode; struct batadv_orig_node *mcast_single_orig = NULL; int network_offset = ETH_HLEN; + __be16 proto;
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) goto dropped; @@ -212,12 +213,15 @@ static int batadv_interface_tx(struct sk_buff *skb, vid = batadv_get_vid(skb, 0); ethhdr = eth_hdr(skb);
- switch (ntohs(ethhdr->h_proto)) { + proto = ethhdr->h_proto; + + switch (ntohs(proto)) { case ETH_P_8021Q: vhdr = vlan_eth_hdr(skb); + proto = vhdr->h_vlan_encapsulated_proto;
/* drop batman-in-batman packets to prevent loops */ - if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) { + if (proto != htons(ETH_P_BATMAN)) { network_offset += VLAN_HLEN; break; } @@ -244,6 +248,9 @@ static int batadv_interface_tx(struct sk_buff *skb, goto dropped; }
+ /* Snoop address candidates from DHCPACKs for early DAT filling */ + batadv_dat_snoop_outgoing_dhcp_ack(bat_priv, skb, proto, vid); + /* don't accept stp packets. STP does not help in meshes. * better use the bridge loop avoidance ... *
Hi,
Haven't looked at the patch itself but it doesn't seem to compile (see the CONFIG_* options):
/home/sven/projekte/build_test/tmp.ZCzmUfnk6m/gen-compat-autoconf.sh /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/compat-autoconf.h /usr/bin/make -C /home/sven/projekte/build_test/linux-build//linux-4.6 M=/home/sven/projekte/build_test/tmp.ZCzmUfnk6m PWD=/home/sven/projekte/build_test/tmp.ZCzmUfnk6m REVISION= CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DEBUG=n CONFIG_BATMAN_ADV_BLA=n CONFIG_BATMAN_ADV_DAT=n CONFIG_BATMAN_ADV_NC=y CONFIG_BATMAN_ADV_MCAST=n CONFIG_BATMAN_ADV_BATMAN_V=n INSTALL_MOD_DIR=updates/ modules make[1]: Entering directory '/home/sven/projekte/build_test/linux-build/linux-4.6' CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/bat_algo.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/bat_iv_ogm.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/bitarray.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/debugfs.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/fragmentation.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/gateway_client.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/gateway_common.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/hard-interface.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/hash.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/icmp_socket.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/main.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/netlink.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/network-coding.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/originator.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/routing.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/send.o CC [M] /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/soft-interface.o scripts/Makefile.build:291: recipe for target '/home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/soft-interface.o' failed scripts/Makefile.build:440: recipe for target '/home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv' failed Makefile:1428: recipe for target '_module_/home/sven/projekte/build_test/tmp.ZCzmUfnk6m' failed make[1]: Leaving directory '/home/sven/projekte/build_test/linux-build/linux-4.6' Makefile:77: recipe for target 'all' failed /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/soft-interface.c:252:9: error: undefined identifier 'batadv_dat_snoop_outgoing_dhcp_ack' /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/soft-interface.c: In function 'batadv_interface_tx': /home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/soft-interface.c:252:2: error: implicit declaration of function 'batadv_dat_snoop_outgoing_dhcp_ack' [-Werror=implicit-function-declaration] batadv_dat_snoop_outgoing_dhcp_ack(bat_priv, skb, proto, vid); ^ cc1: some warnings being treated as errors make[3]: *** [/home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv/soft-interface.o] Error 1 make[2]: *** [/home/sven/projekte/build_test/tmp.ZCzmUfnk6m/net/batman-adv] Error 2 make[1]: *** [_module_/home/sven/projekte/build_test/tmp.ZCzmUfnk6m] Error 2 make: *** [all] Error 2
Kind regards, Sven
On Saturday 02 July 2016 06:09:50 Linus Lüssing wrote: [...]
- if (vid & BATADV_VLAN_HAS_TAG)
skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
vid & VLAN_VID_MASK);
- skb_reset_mac_header(skb);
- return skb;
+}
vlan_insert_tag can return NULL when an error happens. Thus simply doing a skb_reset_mac_header on it without checking skb's value for !NULL is a bad idea.
But you can simply move the skb_reset_mac_header (when it is really necessary) in front of the 'if (vid & BATADV_VLAN_HAS_TAG)'.
Doing it in front would result in (written as absolute values - in reality mac_header is an offset):
skb->mac_header = skb->data skb->data -= VLAN_HLEN skb->mac_header -= VLAN_HLEN
Writing it after the vlan_insert_tag would result in:
skb->data -= VLAN_HLEN skb->mac_header -= VLAN_HLEN skb->mac_header = skb->data
Both calculations should result in skb->mac_header == skb->data
Kind regards, Sven
b.a.t.m.a.n@lists.open-mesh.org