lists.open-mesh.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2023
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
List overview
Download
commits
February 2014
----- 2023 -----
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
commits@lists.open-mesh.org
1 participants
64 discussions
Start a n
N
ew thread
[linux-merge]linux integration; annotated tag, v3.14-rc4, created. v3.14-rc4
by postmaster@open-mesh.org
The annotated tag, v3.14-rc4 has been created at 94de4401e66c81c0a55db01011f770a73eaa79c6 (tag) tagging cfbf8d4857c26a8a307fb7cd258074c9dcd8c691 (commit) replaces v3.14-rc3 tagged by Linus Torvalds on Sun Feb 23 17:40:10 2014 -0800 - Shortlog ------------------------------------------------------------ Linux 3.14-rc4 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTCqL6AAoJEHm+PkMAQRiGljYIAICQIZsXmMc/pUC3hHgTr2KK BBQXjnoE7tDN/QkZQzSj/+VqP1/Ndo7lQlXThXuooNhemjpmFCd8AIRhXi164NPE NoAZ0efWu1kE3iAJKyHN11zVlv4NS0bsTlNAgPN0EwjDBTTk5thfiZBqNz56cWrZ MqH8tKpUTuAPciXeyB6WI34pKMkzB+Urfoweum7euk8WyDw7kthpncwEt+fzBAKm 20+N2JVoHN7h2xuR4mx8rDXPbXlwPCH5K/8NapytbP7xWBJ3UaOjbbcKHbydrfkI 1eOlajXafFrjN/XTXDySqQg9lT6DoszOE0fhAZyrdPPqvbQOU64WdBcYyOg8ObI= =KxaP -----END PGP SIGNATURE----- Antonio Quartulli (9): batman-adv: fix soft-interface MTU computation batman-adv: fix TT-TVLV parsing on OGM reception batman-adv: release vlan object after checking the CRC batman-adv: properly check pskb_may_pull return value batman-adv: avoid potential race condition when adding a new neighbour batman-adv: fix TT CRC computation by ensuring byte order batman-adv: free skb on TVLV parsing success batman-adv: avoid double free when orig_node initialization fails batman-adv: fix potential kernel paging error for unicast transmissions Simon Wunderlich (1): batman-adv: fix potential orig_node reference leak ----------------------------------------------------------------------- -- linux integration
9 years, 1 month
1
0
0
0
[linux-merge]linux integration; branch, merge/master, updated. v3.14-rc1-2091-g9c11ed6
by postmaster@open-mesh.org
The following commit has been merged in the merge/master branch: commit 9c11ed662985e4a48940edc697044d5072fe77a5 Merge: 14d695a7bfadf092dea49a286618303b34417ae6 fb4756fe5f6e58ca2ab208ca634ae4c8dd6e9499 Author: Antonio Quartulli <antonio(a)meshcoding.com> Date: Sun Feb 23 17:29:38 2014 +0100 Merge commit 'fb4756fe5f6e58ca2ab208ca634ae4c8dd6e9499' into merge/master Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com> Conflicts: net/batman-adv/Makefile net/batman-adv/Makefile.kbuild net/batman-adv/compat.h net/batman-adv/gen-compat-autoconf.sh net/batman-adv/sysfs-class-net-mesh diff --combined Documentation/ABI/testing/sysfs-class-net-mesh index 4793d3d,c464062..c464062 --- a/Documentation/ABI/testing/sysfs-class-net-mesh +++ b/Documentation/ABI/testing/sysfs-class-net-mesh @@@ -76,6 -76,15 +76,15 @@@ Description is used to classify clients as "isolated" by the Extended Isolation feature. + What: /sys/class/net/<mesh_iface>/mesh/multicast_mode + Date: Feb 2014 + Contact: Linus Lüssing <linus.luessing(a)web.de> + Description: + Indicates whether multicast optimizations are enabled + or disabled. If set to zero then all nodes in the + mesh are going to use classic flooding for any + multicast packet with no optimizations. + What: /sys/class/net/<mesh_iface>/mesh/network_coding Date: Nov 2012 Contact: Martin Hundeboll <martin(a)hundeboll.net> diff --combined net/batman-adv/Kconfig index fa780b7,0000000..d8ee74c mode 100644,000000..100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig @@@ -1,60 -1,0 +1,68 @@@ +# +# B.A.T.M.A.N meshing protocol +# + +config BATMAN_ADV + tristate "B.A.T.M.A.N. Advanced Meshing Protocol" + depends on NET + select CRC16 + select LIBCRC32C + default n + help + B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is + a routing protocol for multi-hop ad-hoc mesh networks. The + networks may be wired or wireless. See +
http://www.open-mesh.org/
for more information and user space + tools. + +config BATMAN_ADV_BLA + bool "Bridge Loop Avoidance" + depends on BATMAN_ADV && INET + default y + help + This option enables BLA (Bridge Loop Avoidance), a mechanism + to avoid Ethernet frames looping when mesh nodes are connected + to both the same LAN and the same mesh. If you will never use + more than one mesh node in the same LAN, you can safely remove + this feature and save some space. + +config BATMAN_ADV_DAT + bool "Distributed ARP Table" + depends on BATMAN_ADV && INET + default n + help + This option enables DAT (Distributed ARP Table), a DHT based + mechanism that increases ARP reliability on sparse wireless + mesh networks. If you think that your network does not need + this option you can safely remove it and save some space. + +config BATMAN_ADV_NC + bool "Network Coding" + depends on BATMAN_ADV + default n + help + This option enables network coding, a mechanism that aims to + increase the overall network throughput by fusing multiple + packets in one transmission. + Note that interfaces controlled by batman-adv must be manually + configured to have promiscuous mode enabled in order to make + network coding work. + If you think that your network does not need this feature you + can safely disable it and save some space. + ++config BATMAN_ADV_MCAST ++ bool "Multicast optimisation" ++ default n ++ help ++ This option enables the multicast optimisation which aims to ++ reduce the air overhead while improving the reliability of ++ multicast messages. ++ +config BATMAN_ADV_DEBUG + bool "B.A.T.M.A.N. debugging" + depends on BATMAN_ADV + help + This is an option for use by developers; most people should + say N here. This enables compilation of support for + outputting debugging information to the kernel log. The + output is controlled via the module parameter debug. diff --combined net/batman-adv/Makefile index 42df18f,eb7d8c03..eb7d8c03 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile @@@ -36,3 -36,4 +36,4 @@@ batman-adv-y += send. batman-adv-y += soft-interface.o batman-adv-y += sysfs.o batman-adv-y += translation-table.o + batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o diff --combined net/batman-adv/bat_iv_ogm.c index 8323bce,b3bd4ec..b3bd4ec --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@@ -347,10 -347,10 +347,10 @@@ static void batadv_iv_ogm_iface_update_ unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; - memcpy(batadv_ogm_packet->orig, - hard_iface->net_dev->dev_addr, ETH_ALEN); - memcpy(batadv_ogm_packet->prev_sender, - hard_iface->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(batadv_ogm_packet->orig, + hard_iface->net_dev->dev_addr); + ether_addr_copy(batadv_ogm_packet->prev_sender, + hard_iface->net_dev->dev_addr); } static void @@@ -830,7 -830,7 +830,7 @@@ static void batadv_iv_ogm_forward(struc tvlv_len = ntohs(batadv_ogm_packet->tvlv_len); batadv_ogm_packet->ttl--; - memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); + ether_addr_copy(batadv_ogm_packet->prev_sender, ethhdr->h_source); /* apply hop penalty */ batadv_ogm_packet->tq = batadv_hop_penalty(batadv_ogm_packet->tq, diff --combined net/batman-adv/bridge_loop_avoidance.c index 05f0712,6f0d9ec..6f0d9ec --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@@ -191,7 -191,7 +191,7 @@@ batadv_backbone_hash_find(struct batadv if (!hash) return NULL; - memcpy(search_entry.orig, addr, ETH_ALEN); + ether_addr_copy(search_entry.orig, addr); search_entry.vid = vid; index = batadv_choose_backbone_gw(&search_entry, hash->size); @@@ -305,7 -305,7 +305,7 @@@ static void batadv_bla_send_claim(struc /* normal claim frame * set Ethernet SRC to the clients mac */ - memcpy(ethhdr->h_source, mac, ETH_ALEN); + ether_addr_copy(ethhdr->h_source, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): CLAIM %pM on vid %d\n", mac, BATADV_PRINT_VID(vid)); @@@ -314,7 -314,7 +314,7 @@@ /* unclaim frame * set HW SRC to the clients mac */ - memcpy(hw_src, mac, ETH_ALEN); + ether_addr_copy(hw_src, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac, BATADV_PRINT_VID(vid)); @@@ -323,7 -323,7 +323,7 @@@ /* announcement frame * set HW SRC to the special mac containg the crc */ - memcpy(hw_src, mac, ETH_ALEN); + ether_addr_copy(hw_src, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): ANNOUNCE of %pM on vid %d\n", ethhdr->h_source, BATADV_PRINT_VID(vid)); @@@ -333,8 -333,8 +333,8 @@@ * set HW SRC and header destination to the receiving backbone * gws mac */ - memcpy(hw_src, mac, ETH_ALEN); - memcpy(ethhdr->h_dest, mac, ETH_ALEN); + ether_addr_copy(hw_src, mac); + ether_addr_copy(ethhdr->h_dest, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n", ethhdr->h_source, ethhdr->h_dest, @@@ -395,7 -395,7 +395,7 @@@ batadv_bla_get_backbone_gw(struct batad entry->bat_priv = bat_priv; atomic_set(&entry->request_sent, 0); atomic_set(&entry->wait_periods, 0); - memcpy(entry->orig, orig, ETH_ALEN); + ether_addr_copy(entry->orig, orig); /* one for the hash, one for returning */ atomic_set(&entry->refcount, 2); @@@ -563,7 -563,7 +563,7 @@@ static void batadv_bla_add_claim(struc struct batadv_bla_claim search_claim; int hash_added; - memcpy(search_claim.addr, mac, ETH_ALEN); + ether_addr_copy(search_claim.addr, mac); search_claim.vid = vid; claim = batadv_claim_hash_find(bat_priv, &search_claim); @@@ -573,7 -573,7 +573,7 @@@ if (!claim) return; - memcpy(claim->addr, mac, ETH_ALEN); + ether_addr_copy(claim->addr, mac); claim->vid = vid; claim->lasttime = jiffies; claim->backbone_gw = backbone_gw; @@@ -624,7 -624,7 +624,7 @@@ static void batadv_bla_del_claim(struc { struct batadv_bla_claim search_claim, *claim; - memcpy(search_claim.addr, mac, ETH_ALEN); + ether_addr_copy(search_claim.addr, mac); search_claim.vid = vid; claim = batadv_claim_hash_find(bat_priv, &search_claim); if (!claim) @@@ -882,7 -882,7 +882,7 @@@ static int batadv_bla_process_claim(str proto = ethhdr->h_proto; headlen = ETH_HLEN; if (vid & BATADV_VLAN_HAS_TAG) { - vhdr = (struct vlan_ethhdr *)ethhdr; + vhdr = vlan_eth_hdr(skb); proto = vhdr->h_vlan_encapsulated_proto; headlen += VLAN_HLEN; } @@@ -1103,8 -1103,8 +1103,8 @@@ void batadv_bla_update_orig_address(str oldif->net_dev->dev_addr)) continue; - memcpy(backbone_gw->orig, - primary_if->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(backbone_gw->orig, + primary_if->net_dev->dev_addr); /* send an announce frame so others will ask for our * claims and update their tables. */ @@@ -1310,7 -1310,7 +1310,7 @@@ int batadv_bla_check_bcast_duplist(stru entry = &bat_priv->bla.bcast_duplist[curr]; entry->crc = crc; entry->entrytime = jiffies; - memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); + ether_addr_copy(entry->orig, bcast_packet->orig); bat_priv->bla.bcast_duplist_curr = curr; out: @@@ -1458,7 -1458,7 +1458,7 @@@ int batadv_bla_rx(struct batadv_priv *b if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) goto handled; - memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); + ether_addr_copy(search_claim.addr, ethhdr->h_source); search_claim.vid = vid; claim = batadv_claim_hash_find(bat_priv, &search_claim); @@@ -1547,9 -1547,6 +1547,6 @@@ int batadv_bla_tx(struct batadv_priv *b if (!atomic_read(&bat_priv->bridge_loop_avoidance)) goto allow; - /* in VLAN case, the mac header might not be set. */ - skb_reset_mac_header(skb); - if (batadv_bla_process_claim(bat_priv, primary_if, skb)) goto handled; @@@ -1560,7 -1557,7 +1557,7 @@@ if (is_multicast_ether_addr(ethhdr->h_dest)) goto handled; - memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); + ether_addr_copy(search_claim.addr, ethhdr->h_source); search_claim.vid = vid; claim = batadv_claim_hash_find(bat_priv, &search_claim); diff --combined net/batman-adv/distributed-arp-table.c index 5bb37a8,b25fd64..b25fd64 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@@ -277,7 -277,7 +277,7 @@@ static void batadv_dat_entry_add(struc /* if this entry is already known, just update it */ if (dat_entry) { if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr)) - memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); + ether_addr_copy(dat_entry->mac_addr, mac_addr); dat_entry->last_update = jiffies; batadv_dbg(BATADV_DBG_DAT, bat_priv, "Entry updated: %pI4 %pM (vid: %d)\n", @@@ -292,7 -292,7 +292,7 @@@ dat_entry->ip = ip; dat_entry->vid = vid; - memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); + ether_addr_copy(dat_entry->mac_addr, mac_addr); dat_entry->last_update = jiffies; atomic_set(&dat_entry->refcount, 2); diff --combined net/batman-adv/fragmentation.c index 88df9b1,bcc4bea..bcc4bea --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@@ -449,8 -449,8 +449,8 @@@ bool batadv_frag_send_packet(struct sk_ frag_header.reserved = 0; frag_header.no = 0; frag_header.total_size = htons(skb->len); - memcpy(frag_header.orig, primary_if->net_dev->dev_addr, ETH_ALEN); - memcpy(frag_header.dest, orig_node->orig, ETH_ALEN); + ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr); + ether_addr_copy(frag_header.dest, orig_node->orig); /* Eat and send fragments from the tail of skb */ while (skb->len > max_fragment_size) { diff --combined net/batman-adv/gateway_client.c index 55cf226,c835e13..c835e13 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@@ -389,8 -389,6 +389,6 @@@ out batadv_neigh_ifinfo_free_ref(router_gw_tq); if (router_orig_tq) batadv_neigh_ifinfo_free_ref(router_orig_tq); - - return; } /** @@@ -680,7 -678,7 +678,7 @@@ batadv_gw_dhcp_recipient_get(struct sk_ if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) return BATADV_DHCP_NO; - ethhdr = (struct ethhdr *)skb->data; + ethhdr = eth_hdr(skb); proto = ethhdr->h_proto; *header_len += ETH_HLEN; @@@ -689,7 -687,7 +687,7 @@@ if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) return BATADV_DHCP_NO; - vhdr = (struct vlan_ethhdr *)skb->data; + vhdr = vlan_eth_hdr(skb); proto = vhdr->h_vlan_encapsulated_proto; *header_len += VLAN_HLEN; } @@@ -728,7 -726,7 +726,7 @@@ return BATADV_DHCP_NO; /* skb->data might have been reallocated by pskb_may_pull() */ - ethhdr = (struct ethhdr *)skb->data; + ethhdr = eth_hdr(skb); if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); @@@ -765,7 -763,7 +763,7 @@@ if (*p != ETH_ALEN) return BATADV_DHCP_NO; - memcpy(chaddr, skb->data + chaddr_offset, ETH_ALEN); + ether_addr_copy(chaddr, skb->data + chaddr_offset); } return ret; diff --combined net/batman-adv/icmp_socket.c index abb9d6e,bf07dfd..bf07dfd --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@@ -158,6 -158,7 +158,7 @@@ static ssize_t batadv_socket_write(stru struct batadv_orig_node *orig_node = NULL; struct batadv_neigh_node *neigh_node = NULL; size_t packet_len = sizeof(struct batadv_icmp_packet); + uint8_t *addr; if (len < sizeof(struct batadv_icmp_header)) { batadv_dbg(BATADV_DBG_BATMAN, bat_priv, @@@ -227,10 -228,10 +228,10 @@@ goto dst_unreach; icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmp_header; - if (packet_len == sizeof(*icmp_packet_rr)) - memcpy(icmp_packet_rr->rr, - neigh_node->if_incoming->net_dev->dev_addr, - ETH_ALEN); + if (packet_len == sizeof(*icmp_packet_rr)) { + addr = neigh_node->if_incoming->net_dev->dev_addr; + ether_addr_copy(icmp_packet_rr->rr, addr); + } break; default: @@@ -250,7 -251,7 +251,7 @@@ goto free_skb; } - memcpy(icmp_header->orig, primary_if->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(icmp_header->orig, primary_if->net_dev->dev_addr); batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); goto out; diff --combined net/batman-adv/main.c index 66ae135,d1183e8..d1183e8 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@@ -34,6 -34,7 +34,7 @@@ #include "gateway_client.h" #include "bridge_loop_avoidance.h" #include "distributed-arp-table.h" + #include "multicast.h" #include "gateway_common.h" #include "hash.h" #include "bat_algo.h" @@@ -110,6 -111,9 +111,9 @@@ int batadv_mesh_init(struct net_device spin_lock_init(&bat_priv->tt.last_changeset_lock); spin_lock_init(&bat_priv->tt.commit_lock); spin_lock_init(&bat_priv->gw.list_lock); + #ifdef CONFIG_BATMAN_ADV_MCAST + spin_lock_init(&bat_priv->mcast.want_lists_lock); + #endif spin_lock_init(&bat_priv->tvlv.container_list_lock); spin_lock_init(&bat_priv->tvlv.handler_list_lock); spin_lock_init(&bat_priv->softif_vlan_list_lock); @@@ -117,9 -121,17 +121,17 @@@ INIT_HLIST_HEAD(&bat_priv->forw_bat_list); INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); INIT_HLIST_HEAD(&bat_priv->gw.list); + #ifdef CONFIG_BATMAN_ADV_MCAST + INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list); + INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv4_list); + INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv6_list); + #endif INIT_LIST_HEAD(&bat_priv->tt.changes_list); INIT_LIST_HEAD(&bat_priv->tt.req_list); INIT_LIST_HEAD(&bat_priv->tt.roam_list); + #ifdef CONFIG_BATMAN_ADV_MCAST + INIT_HLIST_HEAD(&bat_priv->mcast.mla_list); + #endif INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); @@@ -145,6 -157,7 +157,7 @@@ goto err; batadv_gw_init(bat_priv); + batadv_mcast_init(bat_priv); atomic_set(&bat_priv->gw.reselect, 0); atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); @@@ -169,6 -182,8 +182,8 @@@ void batadv_mesh_free(struct net_devic batadv_dat_free(bat_priv); batadv_bla_free(bat_priv); + batadv_mcast_free(bat_priv); + /* Free the TT and the originator tables only after having terminated * all the other depending components which may use these structures for * their purposes. @@@ -1133,8 -1148,8 +1148,8 @@@ void batadv_tvlv_unicast_send(struct ba unicast_tvlv_packet->reserved = 0; unicast_tvlv_packet->tvlv_len = htons(tvlv_len); unicast_tvlv_packet->align = 0; - memcpy(unicast_tvlv_packet->src, src, ETH_ALEN); - memcpy(unicast_tvlv_packet->dst, dst, ETH_ALEN); + ether_addr_copy(unicast_tvlv_packet->src, src); + ether_addr_copy(unicast_tvlv_packet->dst, dst); tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1); tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff; diff --combined net/batman-adv/main.h index 9374f1a,0000000..515dce7 mode 100644,000000..100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@@ -1,380 -1,0 +1,382 @@@ +/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <
http://www.gnu.org/licenses/
>. + */ + +#ifndef _NET_BATMAN_ADV_MAIN_H_ +#define _NET_BATMAN_ADV_MAIN_H_ + +#define BATADV_DRIVER_AUTHOR "Marek Lindner <mareklindner(a)neomailbox.ch>, " \ + "Simon Wunderlich <sw(a)simonwunderlich.de>" +#define BATADV_DRIVER_DESC "B.A.T.M.A.N. advanced" +#define BATADV_DRIVER_DEVICE "batman-adv" + +#ifndef BATADV_SOURCE_VERSION +#define BATADV_SOURCE_VERSION "2014.1.0" +#endif + +/* B.A.T.M.A.N. parameters */ + +#define BATADV_TQ_MAX_VALUE 255 +#define BATADV_JITTER 20 + +/* Time To Live of broadcast messages */ +#define BATADV_TTL 50 + +/* purge originators after time in seconds if no valid packet comes in + * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE + */ +#define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */ +#define BATADV_TT_LOCAL_TIMEOUT 600000 /* in milliseconds */ +#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */ +#define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */ +#define BATADV_TT_WORK_PERIOD 5000 /* 5 seconds */ +#define BATADV_ORIG_WORK_PERIOD 1000 /* 1 second */ +#define BATADV_DAT_ENTRY_TIMEOUT (5*60000) /* 5 mins in milliseconds */ +/* sliding packet range of received originator messages in sequence numbers + * (should be a multiple of our word size) + */ +#define BATADV_TQ_LOCAL_WINDOW_SIZE 64 +/* milliseconds we have to keep pending tt_req */ +#define BATADV_TT_REQUEST_TIMEOUT 3000 + +#define BATADV_TQ_GLOBAL_WINDOW_SIZE 5 +#define BATADV_TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 +#define BATADV_TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 +#define BATADV_TQ_TOTAL_BIDRECT_LIMIT 1 + +/* number of OGMs sent with the last tt diff */ +#define BATADV_TT_OGM_APPEND_MAX 3 + +/* Time in which a client can roam at most ROAMING_MAX_COUNT times in + * milliseconds + */ +#define BATADV_ROAMING_MAX_TIME 20000 +#define BATADV_ROAMING_MAX_COUNT 5 + +#define BATADV_NO_FLAGS 0 + +#define BATADV_NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */ + +#define BATADV_NO_MARK 0 + +/* default interface for multi interface operation. The default interface is + * used for communication which originated locally (i.e. is not forwarded) + * or where special forwarding is not desired/necessary. + */ +#define BATADV_IF_DEFAULT ((struct batadv_hard_iface *)NULL) + +#define BATADV_NUM_WORDS BITS_TO_LONGS(BATADV_TQ_LOCAL_WINDOW_SIZE) + +#define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ + +/* number of packets to send for broadcasts on different interface types */ +#define BATADV_NUM_BCASTS_DEFAULT 1 +#define BATADV_NUM_BCASTS_WIRELESS 3 +#define BATADV_NUM_BCASTS_MAX 3 + +/* msecs after which an ARP_REQUEST is sent in broadcast as fallback */ +#define ARP_REQ_DELAY 250 +/* numbers of originator to contact for any PUT/GET DHT operation */ +#define BATADV_DAT_CANDIDATES_NUM 3 + +/** + * BATADV_TQ_SIMILARITY_THRESHOLD - TQ points that a secondary metric can differ + * at most from the primary one in order to be still considered acceptable + */ +#define BATADV_TQ_SIMILARITY_THRESHOLD 50 + +/* how much worse secondary interfaces may be to be considered as bonding + * candidates + */ +#define BATADV_BONDING_TQ_THRESHOLD 50 + +/* should not be bigger than 512 bytes or change the size of + * forw_packet->direct_link_flags + */ +#define BATADV_MAX_AGGREGATION_BYTES 512 +#define BATADV_MAX_AGGREGATION_MS 100 + +#define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ +#define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) +#define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) +#define BATADV_BLA_WAIT_PERIODS 3 + +#define BATADV_DUPLIST_SIZE 16 +#define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */ +/* don't reset again within 30 seconds */ +#define BATADV_RESET_PROTECTION_MS 30000 +#define BATADV_EXPECTED_SEQNO_RANGE 65536 + +#define BATADV_NC_NODE_TIMEOUT 10000 /* Milliseconds */ + +enum batadv_mesh_state { + BATADV_MESH_INACTIVE, + BATADV_MESH_ACTIVE, + BATADV_MESH_DEACTIVATING, +}; + +#define BATADV_BCAST_QUEUE_LEN 256 +#define BATADV_BATMAN_QUEUE_LEN 256 + +enum batadv_uev_action { + BATADV_UEV_ADD = 0, + BATADV_UEV_DEL, + BATADV_UEV_CHANGE, +}; + +enum batadv_uev_type { + BATADV_UEV_GW = 0, +}; + +#define BATADV_GW_THRESHOLD 50 + +/* Number of fragment chains for each orig_node */ +#define BATADV_FRAG_BUFFER_COUNT 8 +/* Maximum number of fragments for one packet */ +#define BATADV_FRAG_MAX_FRAGMENTS 16 +/* Maxumim size of each fragment */ +#define BATADV_FRAG_MAX_FRAG_SIZE 1400 +/* Time to keep fragments while waiting for rest of the fragments */ +#define BATADV_FRAG_TIMEOUT 10000 + +#define BATADV_DAT_CANDIDATE_NOT_FOUND 0 +#define BATADV_DAT_CANDIDATE_ORIG 1 + +/* Debug Messages */ +#ifdef pr_fmt +#undef pr_fmt +#endif +/* Append 'batman-adv: ' before kernel messages */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +/* Kernel headers */ + +#include <linux/mutex.h> /* mutex */ +#include <linux/module.h> /* needed by all modules */ +#include <linux/netdevice.h> /* netdevice */ +#include <linux/etherdevice.h> /* ethernet address classification */ +#include <linux/if_ether.h> /* ethernet header */ +#include <linux/poll.h> /* poll_table */ +#include <linux/kthread.h> /* kernel threads */ +#include <linux/pkt_sched.h> /* schedule types */ +#include <linux/workqueue.h> /* workqueue */ +#include <linux/percpu.h> +#include <linux/slab.h> +#include <net/sock.h> /* struct sock */ ++#include <net/addrconf.h> /* ipv6 address stuff */ ++#include <linux/ip.h> +#include <net/rtnetlink.h> +#include <linux/jiffies.h> +#include <linux/seq_file.h> +#include <linux/if_vlan.h> + +#include "types.h" + +#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \ + (int)(vid & VLAN_VID_MASK) : -1) + +extern char batadv_routing_algo[]; +extern struct list_head batadv_hardif_list; + +extern unsigned char batadv_broadcast_addr[]; +extern struct workqueue_struct *batadv_event_workqueue; + +int batadv_mesh_init(struct net_device *soft_iface); +void batadv_mesh_free(struct net_device *soft_iface); +int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr); +struct batadv_hard_iface * +batadv_seq_print_text_primary_if_get(struct seq_file *seq); +int batadv_max_header_len(void); +void batadv_skb_set_priority(struct sk_buff *skb, int offset); +int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *ptype, + struct net_device *orig_dev); +int +batadv_recv_handler_register(uint8_t packet_type, + int (*recv_handler)(struct sk_buff *, + struct batadv_hard_iface *)); +void batadv_recv_handler_unregister(uint8_t packet_type); +int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops); +int batadv_algo_select(struct batadv_priv *bat_priv, char *name); +int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); +__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr); + +/** + * enum batadv_dbg_level - available log levels + * @BATADV_DBG_BATMAN: OGM and TQ computations related messages + * @BATADV_DBG_ROUTES: route added / changed / deleted + * @BATADV_DBG_TT: translation table messages + * @BATADV_DBG_BLA: bridge loop avoidance messages + * @BATADV_DBG_DAT: ARP snooping and DAT related messages + * @BATADV_DBG_NC: network coding related messages + * @BATADV_DBG_ALL: the union of all the above log levels + */ +enum batadv_dbg_level { + BATADV_DBG_BATMAN = BIT(0), + BATADV_DBG_ROUTES = BIT(1), + BATADV_DBG_TT = BIT(2), + BATADV_DBG_BLA = BIT(3), + BATADV_DBG_DAT = BIT(4), + BATADV_DBG_NC = BIT(5), + BATADV_DBG_ALL = 63, +}; + +#ifdef CONFIG_BATMAN_ADV_DEBUG +int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) +__printf(2, 3); + +#define batadv_dbg(type, bat_priv, fmt, arg...) \ + do { \ + if (atomic_read(&bat_priv->log_level) & type) \ + batadv_debug_log(bat_priv, fmt, ## arg);\ + } \ + while (0) +#else /* !CONFIG_BATMAN_ADV_DEBUG */ +__printf(3, 4) +static inline void batadv_dbg(int type __always_unused, + struct batadv_priv *bat_priv __always_unused, + const char *fmt __always_unused, ...) +{ +} +#endif + +#define batadv_info(net_dev, fmt, arg...) \ + do { \ + struct net_device *_netdev = (net_dev); \ + struct batadv_priv *_batpriv = netdev_priv(_netdev); \ + batadv_dbg(BATADV_DBG_ALL, _batpriv, fmt, ## arg); \ + pr_info("%s: " fmt, _netdev->name, ## arg); \ + } while (0) +#define batadv_err(net_dev, fmt, arg...) \ + do { \ + struct net_device *_netdev = (net_dev); \ + struct batadv_priv *_batpriv = netdev_priv(_netdev); \ + batadv_dbg(BATADV_DBG_ALL, _batpriv, fmt, ## arg); \ + pr_err("%s: " fmt, _netdev->name, ## arg); \ + } while (0) + +/* returns 1 if they are the same ethernet addr + * + * note: can't use ether_addr_equal() as it requires aligned memory + */ +static inline int batadv_compare_eth(const void *data1, const void *data2) +{ + return ether_addr_equal_unaligned(data1, data2); +} + +/** + * has_timed_out - compares current time (jiffies) and timestamp + timeout + * @timestamp: base value to compare with (in jiffies) + * @timeout: added to base value before comparing (in milliseconds) + * + * Returns true if current time is after timestamp + timeout + */ +static inline bool batadv_has_timed_out(unsigned long timestamp, + unsigned int timeout) +{ + return time_is_before_jiffies(timestamp + msecs_to_jiffies(timeout)); +} + +#define batadv_atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) + +/* Returns the smallest signed integer in two's complement with the sizeof x */ +#define batadv_smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u))) + +/* Checks if a sequence number x is a predecessor/successor of y. + * they handle overflows/underflows and can correctly check for a + * predecessor/successor unless the variable sequence number has grown by + * more then 2**(bitwidth(x)-1)-1. + * This means that for a uint8_t with the maximum value 255, it would think: + * - when adding nothing - it is neither a predecessor nor a successor + * - before adding more than 127 to the starting value - it is a predecessor, + * - when adding 128 - it is neither a predecessor nor a successor, + * - after adding more than 127 to the starting value - it is a successor + */ +#define batadv_seq_before(x, y) ({typeof(x) _d1 = (x); \ + typeof(y) _d2 = (y); \ + typeof(x) _dummy = (_d1 - _d2); \ + (void) (&_d1 == &_d2); \ + _dummy > batadv_smallest_signed_int(_dummy); }) +#define batadv_seq_after(x, y) batadv_seq_before(y, x) + +/* Stop preemption on local cpu while incrementing the counter */ +static inline void batadv_add_counter(struct batadv_priv *bat_priv, size_t idx, + size_t count) +{ + this_cpu_add(bat_priv->bat_counters[idx], count); +} + +#define batadv_inc_counter(b, i) batadv_add_counter(b, i, 1) + +/* Sum and return the cpu-local counters for index 'idx' */ +static inline uint64_t batadv_sum_counter(struct batadv_priv *bat_priv, + size_t idx) +{ + uint64_t *counters, sum = 0; + int cpu; + + for_each_possible_cpu(cpu) { + counters = per_cpu_ptr(bat_priv->bat_counters, cpu); + sum += counters[idx]; + } + + return sum; +} + +/* Define a macro to reach the control buffer of the skb. The members of the + * control buffer are defined in struct batadv_skb_cb in types.h. + * The macro is inspired by the similar macro TCP_SKB_CB() in tcp.h. + */ +#define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0])) + +void batadv_tvlv_container_register(struct batadv_priv *bat_priv, + uint8_t type, uint8_t version, + void *tvlv_value, uint16_t tvlv_value_len); +uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, + unsigned char **packet_buff, + int *packet_buff_len, + int packet_min_len); +void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv, + struct batadv_ogm_packet *batadv_ogm_packet, + struct batadv_orig_node *orig_node); +void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv, + uint8_t type, uint8_t version); + +void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, + void (*optr)(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig, + uint8_t flags, + void *tvlv_value, + uint16_t tvlv_value_len), + int (*uptr)(struct batadv_priv *bat_priv, + uint8_t *src, uint8_t *dst, + void *tvlv_value, + uint16_t tvlv_value_len), + uint8_t type, uint8_t version, uint8_t flags); +void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv, + uint8_t type, uint8_t version); +int batadv_tvlv_containers_process(struct batadv_priv *bat_priv, + bool ogm_source, + struct batadv_orig_node *orig_node, + uint8_t *src, uint8_t *dst, + void *tvlv_buff, uint16_t tvlv_buff_len); +void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src, + uint8_t *dst, uint8_t type, uint8_t version, + void *tvlv_value, uint16_t tvlv_value_len); +unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len); +bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid); + +#endif /* _NET_BATMAN_ADV_MAIN_H_ */ diff --combined net/batman-adv/multicast.c index 0000000,e69143b..e69143b mode 000000,100644..100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@@ -1,0 -1,773 +1,773 @@@ + /* Copyright (C) 2014 B.A.T.M.A.N. contributors: + * + * Linus Lüssing + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + + #include "main.h" + #include "multicast.h" + #include "originator.h" + #include "hard-interface.h" + #include "translation-table.h" + #include "multicast.h" + + /** + * batadv_mcast_mla_softif_get - get softif multicast listeners + * @dev: the device to collect multicast addresses from + * @mcast_list: a list to put found addresses into + * + * Collect multicast addresses of the local multicast listeners + * on the given soft interface, dev, in the given mcast_list. + * + * Return -ENOMEM on memory allocation error or the number of + * items added to the mcast_list otherwise. + */ + static int batadv_mcast_mla_softif_get(struct net_device *dev, + struct hlist_head *mcast_list) + { + struct netdev_hw_addr *mc_list_entry; + struct batadv_hw_addr *new; + int ret = 0; + + netif_addr_lock_bh(dev); + netdev_for_each_mc_addr(mc_list_entry, dev) { + new = kmalloc(sizeof(*new), GFP_ATOMIC); + if (!new) { + ret = -ENOMEM; + break; + } + + ether_addr_copy(&new->addr, &mc_list_entry->addr); + hlist_add_head(&new->list, mcast_list); + ret++; + } + netif_addr_unlock_bh(dev); + + return ret; + } + + /** + * batadv_mcast_mla_is_duplicate - check whether an address is in a list + * @mcast_addr: the multicast address to check + * @mcast_list: the list with multicast addresses to search in + * + * Return true if the given address is already in the given list. + * Otherwise returns false. + */ + static bool batadv_mcast_mla_is_duplicate(uint8_t *mcast_addr, + struct hlist_head *mcast_list) + { + struct batadv_hw_addr *mcast_entry; + + hlist_for_each_entry(mcast_entry, mcast_list, list) + if (batadv_compare_eth(mcast_entry->addr, mcast_addr)) + return true; + + return false; + } + + /** + * batadv_mcast_mla_list_free - free a list of multicast addresses + * @mcast_list: the list to free + * + * Remove and free all items in the given mcast_list. + */ + static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list) + { + struct batadv_hw_addr *mcast_entry; + struct hlist_node *tmp; + + hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) { + hlist_del(&mcast_entry->list); + kfree(mcast_entry); + } + } + + /** + * batadv_mcast_mla_tt_retract - clean up multicast listener announcements + * @bat_priv: the bat priv with all the soft interface information + * @mcast_list: a list of addresses which should _not_ be removed + * + * Retract the announcement of any multicast listener from the + * translation table except the ones listed in the given mcast_list. + * + * If mcast_list is NULL then all are retracted. + */ + static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv, + struct hlist_head *mcast_list) + { + struct batadv_hw_addr *mcast_entry; + struct hlist_node *tmp; + + hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list, + list) { + if (mcast_list && + batadv_mcast_mla_is_duplicate(mcast_entry->addr, + mcast_list)) + continue; + + batadv_tt_local_remove(bat_priv, mcast_entry->addr, + BATADV_NO_FLAGS, + "mcast TT outdated", false); + + hlist_del(&mcast_entry->list); + kfree(mcast_entry); + } + } + + /** + * batadv_mcast_mla_tt_add - add multicast listener announcements + * @bat_priv: the bat priv with all the soft interface information + * @mcast_list: a list of addresses which are going to get added + * + * Add multicast listener announcements from the given mcast_list to the + * translation table if they have not been added yet. + */ + static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv, + struct hlist_head *mcast_list) + { + struct batadv_hw_addr *mcast_entry; + struct hlist_node *tmp; + + if (!mcast_list) + return; + + hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) { + if (batadv_mcast_mla_is_duplicate(mcast_entry->addr, + &bat_priv->mcast.mla_list)) + continue; + + if (!batadv_tt_local_add(bat_priv->soft_iface, + mcast_entry->addr, BATADV_NO_FLAGS, + BATADV_NULL_IFINDEX, BATADV_NO_MARK)) + continue; + + hlist_del(&mcast_entry->list); + hlist_add_head(&mcast_entry->list, &bat_priv->mcast.mla_list); + } + } + + /** + * batadv_mcast_get_bridge - get the bridge interface on our soft interface + * @bat_priv: the bat priv with all the soft interface information + * + * Return the next bridge interface on top of our soft interface and increase + * its refcount. If no such bridge interface exists, then return NULL. + */ + static struct net_device * + batadv_mcast_get_bridge(struct batadv_priv *bat_priv) + { + struct net_device *upper = bat_priv->soft_iface; + + rcu_read_lock(); + + do { + upper = netdev_master_upper_dev_get_rcu(upper); + } while (upper && !(upper->priv_flags & IFF_EBRIDGE)); + + if (upper) + dev_hold(upper); + + rcu_read_unlock(); + + return upper; + } + + /** + * batadv_mcast_has_bridge - check whether the soft-iface is bridged + * @bat_priv: the bat priv with all the soft interface information + * + * Check whether there is a bridge on top of our soft interface. Return + * true if so, false otherwise. + */ + static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv) + { + struct net_device *bridge; + + bridge = batadv_mcast_get_bridge(bat_priv); + if (!bridge) + goto out; + + dev_put(bridge); + return true; + out: + return false; + } + + /** + * batadv_mcast_mla_tvlv_update - update multicast tvlv + * @bat_priv: the bat priv with all the soft interface information + * + * Update the own multicast tvlv with our current multicast related settings, + * capabilities and inabilities. + * + * Return true if the tvlv container is registered afterwards. Otherwise return + * false. + */ + static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) + { + struct batadv_tvlv_mcast_data mcast_data; + + mcast_data.flags = BATADV_NO_FLAGS; + memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved)); + + /* Avoid attaching MLAs, if there is a bridge on top of our soft + * interface, we don't support that yet (TODO) + */ + if (batadv_mcast_has_bridge(bat_priv)) { + if (bat_priv->mcast.enabled) { + batadv_tvlv_container_unregister(bat_priv, + BATADV_TVLV_MCAST, 1); + bat_priv->mcast.enabled = false; + } + + return false; + } + + if (!bat_priv->mcast.enabled || + mcast_data.flags != bat_priv->mcast.flags) { + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1, + &mcast_data, sizeof(mcast_data)); + bat_priv->mcast.flags = mcast_data.flags; + bat_priv->mcast.enabled = true; + } + + return true; + } + + /** + * batadv_mcast_mla_update - update the own MLAs + * @bat_priv: the bat priv with all the soft interface information + * + * Update the own multicast listener announcements in the translation + * table as well as the own, announced multicast tvlv container. + */ + void batadv_mcast_mla_update(struct batadv_priv *bat_priv) + { + struct net_device *soft_iface = bat_priv->soft_iface; + struct hlist_head mcast_list = HLIST_HEAD_INIT; + int ret; + + if (!batadv_mcast_mla_tvlv_update(bat_priv)) + goto update; + + ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list); + if (ret < 0) + goto out; + + update: + batadv_mcast_mla_tt_retract(bat_priv, &mcast_list); + batadv_mcast_mla_tt_add(bat_priv, &mcast_list); + + out: + batadv_mcast_mla_list_free(&mcast_list); + } + + /** + * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential + * @bat_priv: the bat priv with all the soft interface information + * @skb: the IPv4 packet to check + * @is_unsnoopable: stores whether the destination is snoopable + * + * Check whether the given IPv4 packet has the potential to + * be forwarded with a mode more optimal than classic flooding. + * + * If so then return 0. Otherwise -EINVAL is returned or -ENOMEM if we are + * out of memory. + */ + static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, + struct sk_buff *skb, + bool *is_unsnoopable) + { + struct iphdr *iphdr; + + /* We might fail due to out-of-memory -> drop it */ + if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr))) + return -ENOMEM; + + iphdr = ip_hdr(skb); + + /* TODO: Implement Multicast Router Discovery (RFC4286), + * then allow scope > link local, too + */ + if (!ipv4_is_local_multicast(iphdr->daddr)) + return -EINVAL; + + /* link-local multicast listeners behind a bridge are + * not snoopable (see RFC4541, section 2.1.2.2) + */ + *is_unsnoopable = true; + + return 0; + } + + /** + * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential + * @bat_priv: the bat priv with all the soft interface information + * @skb: the IPv6 packet to check + * @is_unsnoopable: stores whether the destination is snoopable + * + * Check whether the given IPv6 packet has the potential to + * be forwarded with a mode more optimal than classic flooding. + * + * If so then return 0. Otherwise -EINVAL is returned or -ENOMEM if we are + * out of memory. + */ + static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, + struct sk_buff *skb, + bool *is_unsnoopable) + { + struct ipv6hdr *ip6hdr; + + /* We might fail due to out-of-memory -> drop it */ + if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr))) + return -ENOMEM; + + ip6hdr = ipv6_hdr(skb); + + /* TODO: Implement Multicast Router Discovery (RFC4286), + * then allow scope > link local, too + */ + if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != + IPV6_ADDR_SCOPE_LINKLOCAL) + return -EINVAL; + + /* link-local-all-nodes multicast listeners behind a bridge are + * not snoopable (see RFC4541, section 3, paragraph 3) + */ + if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr)) + *is_unsnoopable = true; + + return 0; + } + + /** + * batadv_mcast_forw_mode_check - check for optimized forwarding potential + * @bat_priv: the bat priv with all the soft interface information + * @skb: the multicast frame to check + * @is_unsnoopable: stores whether the destination is snoopable + * + * Check whether the given multicast ethernet frame has the potential to + * be forwarded with a mode more optimal than classic flooding. + * + * If so then return 0. Otherwise -EINVAL is returned or -ENOMEM if we are + * out of memory. + */ + static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, + struct sk_buff *skb, + bool *is_unsnoopable) + { + struct ethhdr *ethhdr = eth_hdr(skb); + + if (!atomic_read(&bat_priv->multicast_mode)) + return -EINVAL; + + if (atomic_read(&bat_priv->mcast.num_disabled)) + return -EINVAL; + + switch (ntohs(ethhdr->h_proto)) { + case ETH_P_IP: + return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb, + is_unsnoopable); + case ETH_P_IPV6: + return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb, + is_unsnoopable); + default: + return -EINVAL; + } + } + + /** + * batadv_mcast_want_all_ip_count - count nodes with unspecific mcast interest + * @bat_priv: the bat priv with all the soft interface information + * @ethhdr: ethernet header of a packet + * + * Return the number of nodes which want all IPv4 multicast traffic if + * the given ethhdr is from an IPv4 packet or the number of nodes which want + * all IPv6 traffic if it matches an IPv6 packet. + */ + static int batadv_mcast_forw_want_all_ip_count(struct batadv_priv *bat_priv, + struct ethhdr *ethhdr) + { + switch (ntohs(ethhdr->h_proto)) { + case ETH_P_IP: + return atomic_read(&bat_priv->mcast.num_want_all_ipv4); + case ETH_P_IPV6: + return atomic_read(&bat_priv->mcast.num_want_all_ipv6); + default: + /* we shouldn't be here... */ + return 0; + } + } + + /** + * batadv_mcast_forw_tt_node_get - get a multicast tt node + * @bat_priv: the bat priv with all the soft interface information + * @ethhdr: the ether header containing the multicast destination + * + * Return an orig_node matching the multicast address provided by ethhdr + * via a translation table lookup. This increases the returned nodes refcount. + */ + static struct batadv_orig_node * + batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv, + struct ethhdr *ethhdr) + { + return batadv_transtable_search(bat_priv, ethhdr->h_source, + ethhdr->h_dest, BATADV_NO_FLAGS); + } + + /** + * batadv_mcast_want_forw_ipv4_node_get - get a node with an ipv4 flag + * @bat_priv: the bat priv with all the soft interface information + * + * Return an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set + * and increase its refcount. + */ + static struct batadv_orig_node * + batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv) + { + struct batadv_orig_node *orig_node; + + rcu_read_lock(); + hlist_for_each_entry_rcu(orig_node, + &bat_priv->mcast.want_all_ipv4_list, + mcast_want_all_ipv4_node) { + if (atomic_inc_not_zero(&orig_node->refcount)) + goto unlock; + } + + orig_node = NULL; + + unlock: + rcu_read_unlock(); + return orig_node; + } + + /** + * batadv_mcast_want_forw_ipv6_node_get - get a node with an ipv6 flag + * @bat_priv: the bat priv with all the soft interface information + * + * Return an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set + * and increase its refcount. + */ + static struct batadv_orig_node * + batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv) + { + struct batadv_orig_node *orig_node; + + rcu_read_lock(); + hlist_for_each_entry_rcu(orig_node, + &bat_priv->mcast.want_all_ipv6_list, + mcast_want_all_ipv6_node) { + if (atomic_inc_not_zero(&orig_node->refcount)) + goto unlock; + } + + orig_node = NULL; + + unlock: + rcu_read_unlock(); + return orig_node; + } + + /** + * batadv_mcast_want_forw_ip_node_get - get a node with an ipv4/ipv6 flag + * @bat_priv: the bat priv with all the soft interface information + * @ethhdr: an ethernet header to determine the protocol family from + * + * Return an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or + * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set + * and increase its refcount. + */ + static struct batadv_orig_node * + batadv_mcast_forw_ip_node_get(struct batadv_priv *bat_priv, + struct ethhdr *ethhdr) + { + switch (ntohs(ethhdr->h_proto)) { + case ETH_P_IP: + return batadv_mcast_forw_ipv4_node_get(bat_priv); + case ETH_P_IPV6: + return batadv_mcast_forw_ipv6_node_get(bat_priv); + default: + /* we shouldn't be here... */ + return NULL; + } + } + + /** + * batadv_mcast_want_forw_unsnoop_node_get - get a node with an unsnoopable flag + * @bat_priv: the bat priv with all the soft interface information + * + * Return an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag set + * and increase its refcount. + */ + static struct batadv_orig_node * + batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv) + { + struct batadv_orig_node *orig_node; + + rcu_read_lock(); + hlist_for_each_entry_rcu(orig_node, + &bat_priv->mcast.want_all_unsnoopables_list, + mcast_want_all_unsnoopables_node) { + if (atomic_inc_not_zero(&orig_node->refcount)) + goto unlock; + } + + orig_node = NULL; + + unlock: + rcu_read_unlock(); + return orig_node; + } + + /** + * batadv_mcast_forw_mode - check on how to forward a multicast packet + * @bat_priv: the bat priv with all the soft interface information + * @skb: The multicast packet to check + * @orig: an originator to be set to forward the skb to + * + * Return the forwarding mode as enum batadv_forw_mode and in case of + * BATADV_FORW_SINGLE set the orig to the single originator the skb + * should be forwarded to. + */ + enum batadv_forw_mode + batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, + struct batadv_orig_node **orig) + { + struct ethhdr *ethhdr; + bool is_unsnoopable = false; + int ret, tt_count, ip_count, unsnoop_count, total_count; + + ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable); + if (ret == -ENOMEM) + return BATADV_FORW_NONE; + else if (ret < 0) + return BATADV_FORW_ALL; + + ethhdr = eth_hdr(skb); + + tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest, + BATADV_NO_FLAGS); + ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr); + unsnoop_count = !is_unsnoopable ? 0 : + atomic_read(&bat_priv->mcast.num_want_all_unsnoopables); + + total_count = tt_count + ip_count + unsnoop_count; + + switch (total_count) { + case 1: + if (tt_count) + *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr); + else if (ip_count) + *orig = batadv_mcast_forw_ip_node_get(bat_priv, ethhdr); + else if (unsnoop_count) + *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv); + + if (*orig) + return BATADV_FORW_SINGLE; + + /* fall through */ + case 0: + return BATADV_FORW_NONE; + default: + return BATADV_FORW_ALL; + } + } + + /** + * batadv_mcast_want_unsnoop_update - update unsnoop counter and list + * @bat_priv: the bat priv with all the soft interface information + * @orig: the orig_node which multicast state might have changed of + * @mcast_flags: flags indicating the new multicast state + * + * If the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag of this originator, + * orig, has toggled then this method updates counter and list accordingly. + */ + static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig, + uint8_t mcast_flags) + { + /* switched from flag unset to set */ + if (mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES && + !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)) { + atomic_inc(&bat_priv->mcast.num_want_all_unsnoopables); + + spin_lock_bh(&bat_priv->mcast.want_lists_lock); + hlist_add_head_rcu(&orig->mcast_want_all_unsnoopables_node, + &bat_priv->mcast.want_all_unsnoopables_list); + spin_unlock_bh(&bat_priv->mcast.want_lists_lock); + /* switched from flag set to unset */ + } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) && + orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) { + atomic_dec(&bat_priv->mcast.num_want_all_unsnoopables); + + spin_lock_bh(&bat_priv->mcast.want_lists_lock); + hlist_del_rcu(&orig->mcast_want_all_unsnoopables_node); + spin_unlock_bh(&bat_priv->mcast.want_lists_lock); + } + } + + /** + * batadv_mcast_want_ipv4_update - update want-all-ipv4 counter and list + * @bat_priv: the bat priv with all the soft interface information + * @orig: the orig_node which multicast state might have changed of + * @mcast_flags: flags indicating the new multicast state + * + * If the BATADV_MCAST_WANT_ALL_IPV4 flag of this originator, orig, has + * toggled then this method updates counter and list accordingly. + */ + static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig, + uint8_t mcast_flags) + { + /* switched from flag unset to set */ + if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV4 && + !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4)) { + atomic_inc(&bat_priv->mcast.num_want_all_ipv4); + + spin_lock_bh(&bat_priv->mcast.want_lists_lock); + hlist_add_head_rcu(&orig->mcast_want_all_ipv4_node, + &bat_priv->mcast.want_all_ipv4_list); + spin_unlock_bh(&bat_priv->mcast.want_lists_lock); + /* switched from flag set to unset */ + } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) && + orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) { + atomic_dec(&bat_priv->mcast.num_want_all_ipv4); + + spin_lock_bh(&bat_priv->mcast.want_lists_lock); + hlist_del_rcu(&orig->mcast_want_all_ipv4_node); + spin_unlock_bh(&bat_priv->mcast.want_lists_lock); + } + } + + /** + * batadv_mcast_want_ipv6_update - update want-all-ipv6 counter and list + * @bat_priv: the bat priv with all the soft interface information + * @orig: the orig_node which multicast state might have changed of + * @mcast_flags: flags indicating the new multicast state + * + * If the BATADV_MCAST_WANT_ALL_IPV6 flag of this originator, orig, has + * toggled then this method updates counter and list accordingly. + */ + static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig, + uint8_t mcast_flags) + { + /* switched from flag unset to set */ + if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV6 && + !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6)) { + atomic_inc(&bat_priv->mcast.num_want_all_ipv6); + + spin_lock_bh(&bat_priv->mcast.want_lists_lock); + hlist_add_head_rcu(&orig->mcast_want_all_ipv6_node, + &bat_priv->mcast.want_all_ipv6_list); + spin_unlock_bh(&bat_priv->mcast.want_lists_lock); + /* switched from flag set to unset */ + } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) && + orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) { + atomic_dec(&bat_priv->mcast.num_want_all_ipv6); + + spin_lock_bh(&bat_priv->mcast.want_lists_lock); + hlist_del_rcu(&orig->mcast_want_all_ipv6_node); + spin_unlock_bh(&bat_priv->mcast.want_lists_lock); + } + } + + /** + * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container + * @bat_priv: the bat priv with all the soft interface information + * @orig: the orig_node of the ogm + * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) + * @tvlv_value: tvlv buffer containing the multicast data + * @tvlv_value_len: tvlv buffer length + */ + static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig, + uint8_t flags, + void *tvlv_value, + uint16_t tvlv_value_len) + { + bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND); + uint8_t mcast_flags = BATADV_NO_FLAGS; + bool orig_initialized; + + orig_initialized = orig->capa_initialized & BATADV_ORIG_CAPA_HAS_MCAST; + + /* If mcast support is turned on decrease the disabled mcast node + * counter only if we had increased it for this node before. If this + * is a completely new orig_node no need to decrease the counter. + */ + if (orig_mcast_enabled && + !(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) { + if (orig_initialized) + atomic_dec(&bat_priv->mcast.num_disabled); + orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST; + /* If mcast support is being switched off increase the disabled + * mcast node counter. + */ + } else if (!orig_mcast_enabled && + orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) { + atomic_inc(&bat_priv->mcast.num_disabled); + orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST; + } + + orig->capa_initialized |= BATADV_ORIG_CAPA_HAS_MCAST; + + if (orig_mcast_enabled && tvlv_value && + (tvlv_value_len >= sizeof(mcast_flags))) + mcast_flags = *(uint8_t *)tvlv_value; + + batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags); + batadv_mcast_want_ipv4_update(bat_priv, orig, mcast_flags); + batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags); + + orig->mcast_flags = mcast_flags; + } + + /** + * batadv_mcast_init - initialize the multicast optimizations structures + * @bat_priv: the bat priv with all the soft interface information + */ + void batadv_mcast_init(struct batadv_priv *bat_priv) + { + batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1, + NULL, BATADV_TVLV_MCAST, 1, + BATADV_TVLV_HANDLER_OGM_CIFNOTFND); + } + + /** + * batadv_mcast_free - free the multicast optimizations structures + * @bat_priv: the bat priv with all the soft interface information + */ + void batadv_mcast_free(struct batadv_priv *bat_priv) + { + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1); + batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1); + + batadv_mcast_mla_tt_retract(bat_priv, NULL); + } + + /** + * batadv_mcast_purge_orig - reset originator global mcast state modifications + * @orig: the originator which is going to get purged + */ + void batadv_mcast_purge_orig(struct batadv_orig_node *orig) + { + struct batadv_priv *bat_priv = orig->bat_priv; + + if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) + atomic_dec(&bat_priv->mcast.num_disabled); + + batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); + batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS); + batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS); + } diff --combined net/batman-adv/multicast.h index 0000000,a76bc3a..a76bc3a mode 000000,100644..100644 --- a/net/batman-adv/multicast.h +++ b/net/batman-adv/multicast.h @@@ -1,0 -1,77 +1,77 @@@ + /* Copyright (C) 2014 B.A.T.M.A.N. contributors: + * + * Linus Lüssing + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + + #ifndef _NET_BATMAN_ADV_MULTICAST_H_ + #define _NET_BATMAN_ADV_MULTICAST_H_ + + /** + * batadv_forw_mode - the way a packet should be forwarded as + * @BATADV_FORW_ALL: forward the packet to all nodes + * (currently via classic flooding) + * @BATADV_FORW_SINGLE: forward the packet to a single node + * (currently via the BATMAN unicast routing protocol) + * @BATADV_FORW_NONE: don't forward, drop it + */ + enum batadv_forw_mode { + BATADV_FORW_ALL, + BATADV_FORW_SINGLE, + BATADV_FORW_NONE, + }; + + #ifdef CONFIG_BATMAN_ADV_MCAST + + void batadv_mcast_mla_update(struct batadv_priv *bat_priv); + + enum batadv_forw_mode + batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, + struct batadv_orig_node **mcast_single_orig); + + void batadv_mcast_init(struct batadv_priv *bat_priv); + + void batadv_mcast_free(struct batadv_priv *bat_priv); + + void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); + + #else + + static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv) + { + return; + } + + static inline enum batadv_forw_mode + batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, + struct batadv_orig_node **mcast_single_orig) + { + return BATADV_FORW_ALL; + } + + static inline int batadv_mcast_init(struct batadv_priv *bat_priv) + { + return 0; + } + + static inline void batadv_mcast_free(struct batadv_priv *bat_priv) + { + return; + } + + static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node) + { + return; + } + + #endif /* CONFIG_BATMAN_ADV_MCAST */ + + #endif /* _NET_BATMAN_ADV_MULTICAST_H_ */ diff --combined net/batman-adv/network-coding.c index f1b604d,a9546fe..a9546fe --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@@ -819,7 -819,7 +819,7 @@@ static struct batadv_nc_nod /* Initialize nc_node */ INIT_LIST_HEAD(&nc_node->list); - memcpy(nc_node->addr, orig_node->orig, ETH_ALEN); + ether_addr_copy(nc_node->addr, orig_node->orig); nc_node->orig_node = orig_neigh_node; atomic_set(&nc_node->refcount, 2); @@@ -941,8 -941,8 +941,8 @@@ static struct batadv_nc_path *batadv_nc spin_lock_init(&nc_path->packet_list_lock); atomic_set(&nc_path->refcount, 2); nc_path->last_valid = jiffies; - memcpy(nc_path->next_hop, dst, ETH_ALEN); - memcpy(nc_path->prev_hop, src, ETH_ALEN); + ether_addr_copy(nc_path->next_hop, dst); + ether_addr_copy(nc_path->prev_hop, src); batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n", nc_path->prev_hop, @@@ -1114,15 -1114,15 +1114,15 @@@ static bool batadv_nc_code_packets(stru coded_packet->ttl = packet1->ttl; /* Info about first unicast packet */ - memcpy(coded_packet->first_source, first_source, ETH_ALEN); - memcpy(coded_packet->first_orig_dest, packet1->dest, ETH_ALEN); + ether_addr_copy(coded_packet->first_source, first_source); + ether_addr_copy(coded_packet->first_orig_dest, packet1->dest); coded_packet->first_crc = packet_id1; coded_packet->first_ttvn = packet1->ttvn; /* Info about second unicast packet */ - memcpy(coded_packet->second_dest, second_dest, ETH_ALEN); - memcpy(coded_packet->second_source, second_source, ETH_ALEN); - memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN); + ether_addr_copy(coded_packet->second_dest, second_dest); + ether_addr_copy(coded_packet->second_source, second_source); + ether_addr_copy(coded_packet->second_orig_dest, packet2->dest); coded_packet->second_crc = packet_id2; coded_packet->second_ttl = packet2->ttl; coded_packet->second_ttvn = packet2->ttvn; @@@ -1349,8 -1349,8 +1349,8 @@@ static void batadv_nc_skb_store_before_ /* Set the mac header as if we actually sent the packet uncoded */ ethhdr = eth_hdr(skb); - memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN); - memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN); + ether_addr_copy(ethhdr->h_source, ethhdr->h_dest); + ether_addr_copy(ethhdr->h_dest, eth_dst_new); /* Set data pointer to MAC header to mimic packets from our tx path */ skb_push(skb, ETH_HLEN); @@@ -1636,7 -1636,7 +1636,7 @@@ batadv_nc_skb_decode_packet(struct bata /* Reconstruct original mac header */ ethhdr = eth_hdr(skb); - memcpy(ethhdr, ðhdr_tmp, sizeof(*ethhdr)); + *ethhdr = ethhdr_tmp; /* Select the correct unicast header information based on the location * of our mac address in the coded_packet header @@@ -1646,7 -1646,7 +1646,7 @@@ * so the Ethernet address must be copied to h_dest and * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST */ - memcpy(ethhdr->h_dest, coded_packet_tmp.second_dest, ETH_ALEN); + ether_addr_copy(ethhdr->h_dest, coded_packet_tmp.second_dest); skb->pkt_type = PACKET_HOST; orig_dest = coded_packet_tmp.second_orig_dest; @@@ -1682,7 -1682,7 +1682,7 @@@ unicast_packet->packet_type = BATADV_UNICAST; unicast_packet->version = BATADV_COMPAT_VERSION; unicast_packet->ttl = ttl; - memcpy(unicast_packet->dest, orig_dest, ETH_ALEN); + ether_addr_copy(unicast_packet->dest, orig_dest); unicast_packet->ttvn = ttvn; batadv_nc_packet_free(nc_packet); diff --combined net/batman-adv/originator.c index 8539416,ffd9dfb..ffd9dfb --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@@ -27,6 -27,7 +27,7 @@@ #include "bridge_loop_avoidance.h" #include "network-coding.h" #include "fragmentation.h" + #include "multicast.h" /* hash class keys */ static struct lock_class_key batadv_orig_hash_lock_class_key; @@@ -446,7 -447,7 +447,7 @@@ batadv_neigh_node_new(struct batadv_har INIT_HLIST_HEAD(&neigh_node->ifinfo_list); spin_lock_init(&neigh_node->ifinfo_lock); - memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); + ether_addr_copy(neigh_node->addr, neigh_addr); neigh_node->if_incoming = hard_iface; neigh_node->orig_node = orig_node; @@@ -557,6 -558,8 +558,8 @@@ static void batadv_orig_node_free_rcu(s } spin_unlock_bh(&orig_node->neigh_list_lock); + batadv_mcast_purge_orig(orig_node); + /* Free nc_nodes */ batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); @@@ -664,15 -667,17 +667,17 @@@ struct batadv_orig_node *batadv_orig_no /* extra reference for return */ atomic_set(&orig_node->refcount, 2); - orig_node->tt_initialised = false; orig_node->bat_priv = bat_priv; - memcpy(orig_node->orig, addr, ETH_ALEN); + ether_addr_copy(orig_node->orig, addr); batadv_dat_init_orig_node_addr(orig_node); atomic_set(&orig_node->last_ttvn, 0); orig_node->tt_buff = NULL; orig_node->tt_buff_len = 0; reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); orig_node->bcast_seqno_reset = reset_time; + #ifdef CONFIG_BATMAN_ADV_MCAST + orig_node->mcast_flags = BATADV_NO_FLAGS; + #endif /* create a vlan object for the "untagged" LAN */ vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); diff --combined net/batman-adv/packet.h index 0a381d1,feaa336..feaa336 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@@ -89,6 -89,19 +89,19 @@@ enum batadv_icmp_packettype BATADV_PARAMETER_PROBLEM = 12, }; + /** + * enum batadv_mcast_flags - flags for multicast capabilities and settings + * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for + * 224.0.0.0/24 or ff02::1 + * @BATADV_MCAST_WANT_ALL_IPV4: we want all IPv4 multicast packets + * @BATADV_MCAST_WANT_ALL_IPV6: we want all IPv6 multicast packets + */ + enum batadv_mcast_flags { + BATADV_MCAST_WANT_ALL_UNSNOOPABLES = BIT(0), + BATADV_MCAST_WANT_ALL_IPV4 = BIT(1), + BATADV_MCAST_WANT_ALL_IPV6 = BIT(2), + }; + /* tt data subtypes */ #define BATADV_TT_DATA_TYPE_MASK 0x0F @@@ -145,6 -158,7 +158,7 @@@ enum batadv_bla_claimframe * @BATADV_TVLV_NC: network coding tvlv * @BATADV_TVLV_TT: translation table tvlv * @BATADV_TVLV_ROAM: roaming advertisement tvlv + * @BATADV_TVLV_MCAST: multicast capability tvlv */ enum batadv_tvlv_type { BATADV_TVLV_GW = 0x01, @@@ -152,6 -166,7 +166,7 @@@ BATADV_TVLV_NC = 0x03, BATADV_TVLV_TT = 0x04, BATADV_TVLV_ROAM = 0x05, + BATADV_TVLV_MCAST = 0x06, }; #pragma pack(2) @@@ -504,4 -519,14 +519,14 @@@ struct batadv_tvlv_roam_adv __be16 vid; }; + /** + * struct batadv_tvlv_mcast_data - payload of a multicast tvlv + * @flags: multicast flags announced by the orig node + * @reserved: reserved field + */ + struct batadv_tvlv_mcast_data { + uint8_t flags; + uint8_t reserved[3]; + }; + #endif /* _NET_BATMAN_ADV_PACKET_H_ */ diff --combined net/batman-adv/routing.c index a953d5b,3855132..3855132 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@@ -222,8 -222,8 +222,8 @@@ static int batadv_recv_my_icmp_packet(s icmph = (struct batadv_icmp_header *)skb->data; - memcpy(icmph->dst, icmph->orig, ETH_ALEN); - memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(icmph->dst, icmph->orig); + ether_addr_copy(icmph->orig, primary_if->net_dev->dev_addr); icmph->msg_type = BATADV_ECHO_REPLY; icmph->ttl = BATADV_TTL; @@@ -276,9 -276,8 +276,8 @@@ static int batadv_recv_icmp_ttl_exceede icmp_packet = (struct batadv_icmp_packet *)skb->data; - memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); - memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, - ETH_ALEN); + ether_addr_copy(icmp_packet->dst, icmp_packet->orig); + ether_addr_copy(icmp_packet->orig, primary_if->net_dev->dev_addr); icmp_packet->msg_type = BATADV_TTL_EXCEEDED; icmp_packet->ttl = BATADV_TTL; @@@ -341,8 -340,8 +340,8 @@@ int batadv_recv_icmp_packet(struct sk_b if (icmp_packet_rr->rr_cur >= BATADV_RR_LEN) goto out; - memcpy(&(icmp_packet_rr->rr[icmp_packet_rr->rr_cur]), - ethhdr->h_dest, ETH_ALEN); + ether_addr_copy(&(icmp_packet_rr->rr[icmp_packet_rr->rr_cur]), + ethhdr->h_dest); icmp_packet_rr->rr_cur++; } @@@ -664,7 -663,7 +663,7 @@@ batadv_reroute_unicast_packet(struct ba } /* update the packet header */ - memcpy(unicast_packet->dest, orig_addr, ETH_ALEN); + ether_addr_copy(unicast_packet->dest, orig_addr); unicast_packet->ttvn = orig_ttvn; ret = true; @@@ -774,7 -773,7 +773,7 @@@ static int batadv_check_unicast_ttvn(st if (!primary_if) return 0; - memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(unicast_packet->dest, primary_if->net_dev->dev_addr); batadv_hardif_free_ref(primary_if); diff --combined net/batman-adv/send.c index 1703a2e,d27161e..d27161e --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@@ -27,6 -27,7 +27,7 @@@ #include "originator.h" #include "network-coding.h" #include "fragmentation.h" + #include "multicast.h" static void batadv_send_outstanding_bcast_packet(struct work_struct *work); @@@ -59,8 -60,8 +60,8 @@@ int batadv_send_skb_packet(struct sk_bu skb_reset_mac_header(skb); ethhdr = eth_hdr(skb); - memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN); - memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN); + ether_addr_copy(ethhdr->h_source, hard_iface->net_dev->dev_addr); + ether_addr_copy(ethhdr->h_dest, dst_addr); ethhdr->h_proto = htons(ETH_P_BATMAN); skb_set_network_header(skb, ETH_HLEN); @@@ -165,7 -166,7 +166,7 @@@ batadv_send_skb_push_fill_unicast(struc /* set unicast ttl */ unicast_packet->ttl = BATADV_TTL; /* copy the destination for faster routing */ - memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); + ether_addr_copy(unicast_packet->dest, orig_node->orig); /* set the destination tt version number */ unicast_packet->ttvn = ttvn; @@@ -220,7 -221,7 +221,7 @@@ bool batadv_send_skb_prepare_unicast_4a uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR; - memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(uc_4addr_packet->src, primary_if->net_dev->dev_addr); uc_4addr_packet->subtype = packet_subtype; uc_4addr_packet->reserved = 0; @@@ -248,14 -249,14 +249,14 @@@ out * * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */ - static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, - struct sk_buff *skb, int packet_type, - int packet_subtype, - struct batadv_orig_node *orig_node, - unsigned short vid) + int batadv_send_skb_unicast(struct batadv_priv *bat_priv, + struct sk_buff *skb, int packet_type, + int packet_subtype, + struct batadv_orig_node *orig_node, + unsigned short vid) { - struct ethhdr *ethhdr; struct batadv_unicast_packet *unicast_packet; + struct ethhdr *ethhdr; int ret = NET_XMIT_DROP; if (!orig_node) @@@ -311,6 -312,7 +312,7 @@@ out * @packet_type: the batman unicast packet type to use * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast * 4addr packets) + * @dst_hint: can be used to override the destination contained in the skb * @vid: the vid to be used to search the translation table * * Look up the recipient node for the destination address in the ethernet diff --combined net/batman-adv/send.h index aaddaa9,38d0ec1..38d0ec1 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h @@@ -36,6 -36,11 +36,11 @@@ bool batadv_send_skb_prepare_unicast_4a struct sk_buff *skb, struct batadv_orig_node *orig_node, int packet_subtype); + int batadv_send_skb_unicast(struct batadv_priv *bat_priv, + struct sk_buff *skb, int packet_type, + int packet_subtype, + struct batadv_orig_node *orig_node, + unsigned short vid); int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, struct sk_buff *skb, int packet_type, int packet_subtype, uint8_t *dst_hint, @@@ -47,6 -52,7 +52,7 @@@ int batadv_send_skb_via_gw(struct batad * batadv_send_skb_via_tt - send an skb via TT lookup * @bat_priv: the bat priv with all the soft interface information * @skb: the payload to send + * @dst_hint: can be used to override the destination contained in the skb * @vid: the vid to be used to search the translation table * * Look up the recipient node for the destination address in the ethernet @@@ -68,6 -74,7 +74,7 @@@ static inline int batadv_send_skb_via_t * @bat_priv: the bat priv with all the soft interface information * @skb: the payload to send * @packet_subtype: the unicast 4addr packet subtype to use + * @dst_hint: can be used to override the destination contained in the skb * @vid: the vid to be used to search the translation table * * Look up the recipient node for the destination address in the ethernet diff --combined net/batman-adv/soft-interface.c index f82c267,744a59b..744a59b --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@@ -32,6 -32,7 +32,7 @@@ #include <linux/ethtool.h> #include <linux/etherdevice.h> #include <linux/if_vlan.h> + #include "multicast.h" #include "bridge_loop_avoidance.h" #include "network-coding.h" @@@ -111,8 -112,8 +112,8 @@@ static int batadv_interface_set_mac_add if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - memcpy(old_addr, dev->dev_addr, ETH_ALEN); - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + ether_addr_copy(old_addr, dev->dev_addr); + ether_addr_copy(dev->dev_addr, addr->sa_data); /* only modify transtable if it has been initialized before */ if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { @@@ -170,17 -171,19 +171,19 @@@ static int batadv_interface_tx(struct s unsigned short vid; uint32_t seqno; int gw_mode; + enum batadv_forw_mode forw_mode; + struct batadv_orig_node *mcast_single_orig = NULL; if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) goto dropped; soft_iface->trans_start = jiffies; vid = batadv_get_vid(skb, 0); - ethhdr = (struct ethhdr *)skb->data; + ethhdr = eth_hdr(skb); switch (ntohs(ethhdr->h_proto)) { case ETH_P_8021Q: - vhdr = (struct vlan_ethhdr *)skb->data; + vhdr = vlan_eth_hdr(skb); if (vhdr->h_vlan_encapsulated_proto != ethertype) break; @@@ -194,7 -197,7 +197,7 @@@ goto dropped; /* skb->data might have been reallocated by batadv_bla_tx() */ - ethhdr = (struct ethhdr *)skb->data; + ethhdr = eth_hdr(skb); /* Register the client MAC in the transtable */ if (!is_multicast_ether_addr(ethhdr->h_source)) { @@@ -230,7 -233,7 +233,7 @@@ /* skb->data may have been modified by * batadv_gw_dhcp_recipient_get() */ - ethhdr = (struct ethhdr *)skb->data; + ethhdr = eth_hdr(skb); /* if gw_mode is on, broadcast any non-DHCP message. * All the DHCP packets are going to be sent as unicast */ @@@ -247,9 -250,19 +250,19 @@@ * directed to a DHCP server */ goto dropped; - } send: + if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) { + forw_mode = batadv_mcast_forw_mode(bat_priv, skb, + &mcast_single_orig); + if (forw_mode == BATADV_FORW_NONE) + goto dropped; + + if (forw_mode == BATADV_FORW_SINGLE) + do_bcast = false; + } + } + batadv_skb_set_priority(skb, 0); /* ethernet packet should be broadcasted */ @@@ -279,8 -292,8 +292,8 @@@ /* hw address of first interface is the orig mac because only * this mac is known throughout the mesh */ - memcpy(bcast_packet->orig, - primary_if->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(bcast_packet->orig, + primary_if->net_dev->dev_addr); /* set broadcast sequence number */ seqno = atomic_inc_return(&bat_priv->bcast_seqno); @@@ -301,6 -314,10 +314,10 @@@ if (ret) goto dropped; ret = batadv_send_skb_via_gw(bat_priv, skb, vid); + } else if (mcast_single_orig) { + ret = batadv_send_skb_unicast(bat_priv, skb, + BATADV_UNICAST, 0, + mcast_single_orig, vid); } else { if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) @@@ -652,10 -669,7 +669,7 @@@ static void batadv_softif_destroy_finis } batadv_sysfs_del_meshif(soft_iface); - - rtnl_lock(); - unregister_netdevice(soft_iface); - rtnl_unlock(); + unregister_netdev(soft_iface); } /** @@@ -692,6 -706,14 +706,14 @@@ static int batadv_softif_init_late(stru #ifdef CONFIG_BATMAN_ADV_DAT atomic_set(&bat_priv->distributed_arp_table, 1); #endif + #ifdef CONFIG_BATMAN_ADV_MCAST + bat_priv->mcast.flags = BATADV_NO_FLAGS; + atomic_set(&bat_priv->multicast_mode, 1); + atomic_set(&bat_priv->mcast.num_disabled, 0); + atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); + atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); + atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); + #endif atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); atomic_set(&bat_priv->gw_sel_class, 20); atomic_set(&bat_priv->gw.bandwidth_down, 100); diff --combined net/batman-adv/sysfs.c index e456bf6,1ebb0d9..1ebb0d9 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@@ -539,6 -539,9 +539,9 @@@ BATADV_ATTR_SIF_UINT(gw_sel_class, S_IR batadv_post_gw_reselect); static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, batadv_store_gw_bwidth); + #ifdef CONFIG_BATMAN_ADV_MCAST + BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL); + #endif #ifdef CONFIG_BATMAN_ADV_DEBUG BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); #endif @@@ -558,6 -561,9 +561,9 @@@ static struct batadv_attribute *batadv_ #ifdef CONFIG_BATMAN_ADV_DAT &batadv_attr_distributed_arp_table, #endif + #ifdef CONFIG_BATMAN_ADV_MCAST + &batadv_attr_multicast_mode, + #endif &batadv_attr_fragmentation, &batadv_attr_routing_algo, &batadv_attr_gw_mode, diff --combined net/batman-adv/translation-table.c index 959dde7,dab5c39..dab5c39 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@@ -24,6 -24,7 +24,7 @@@ #include "originator.h" #include "routing.h" #include "bridge_loop_avoidance.h" + #include "multicast.h" #include <linux/crc32c.h> @@@ -96,7 -97,7 +97,7 @@@ batadv_tt_hash_find(struct batadv_hasht if (!hash) return NULL; - memcpy(to_search.addr, addr, ETH_ALEN); + ether_addr_copy(to_search.addr, addr); to_search.vid = vid; index = batadv_choose_tt(&to_search, hash->size); @@@ -192,6 -193,32 +193,32 @@@ batadv_tt_global_entry_free_ref(struct } } + /** + * batadv_tt_global_hash_count - count the number of orig entries + * @hash: hash table containing the tt entries + * @addr: the mac address of the client to count entries for + * @vid: VLAN identifier + * + * Return the number of originators advertising the given address/data + * (excluding ourself). + */ + int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, + const uint8_t *addr, unsigned short vid) + { + struct batadv_tt_global_entry *tt_global_entry; + int count = 0; + + tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid); + if (!tt_global_entry) + goto out; + + count = atomic_read(&tt_global_entry->orig_list_count); + batadv_tt_global_entry_free_ref(tt_global_entry); + + out: + return count; + } + static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) { struct batadv_tt_orig_list_entry *orig_entry; @@@ -333,7 -360,7 +360,7 @@@ static void batadv_tt_local_event(struc tt_change_node->change.flags = flags; memset(tt_change_node->change.reserved, 0, sizeof(tt_change_node->change.reserved)); - memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN); + ether_addr_copy(tt_change_node->change.addr, common->addr); tt_change_node->change.vid = htons(common->vid); del_op_requested = flags & BATADV_TT_CLIENT_DEL; @@@ -484,7 -511,7 +511,7 @@@ bool batadv_tt_local_add(struct net_dev { struct batadv_priv *bat_priv = netdev_priv(soft_iface); struct batadv_tt_local_entry *tt_local; - struct batadv_tt_global_entry *tt_global; + struct batadv_tt_global_entry *tt_global = NULL; struct net_device *in_dev = NULL; struct hlist_head *head; struct batadv_tt_orig_list_entry *orig_entry; @@@ -497,7 -524,9 +524,9 @@@ in_dev = dev_get_by_index(&init_net, ifindex); tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid); - tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid); + + if (!is_multicast_ether_addr(addr)) + tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid); if (tt_local) { tt_local->last_seen = jiffies; @@@ -549,7 -578,7 +578,7 @@@ addr, BATADV_PRINT_VID(vid), (uint8_t)atomic_read(&bat_priv->tt.vn)); - memcpy(tt_local->common.addr, addr, ETH_ALEN); + ether_addr_copy(tt_local->common.addr, addr); /* The local entry has to be marked as NEW to avoid to send it in * a full table response going out before the next ttvn increment * (consistency check) @@@ -562,8 -591,11 +591,11 @@@ tt_local->last_seen = jiffies; tt_local->common.added_at = tt_local->last_seen; - /* the batman interface mac address should never be purged */ - if (batadv_compare_eth(addr, soft_iface->dev_addr)) + /* the batman interface mac and multicast addresses should never be + * purged + */ + if (batadv_compare_eth(addr, soft_iface->dev_addr) || + is_multicast_ether_addr(addr)) tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, @@@ -1219,6 -1251,8 +1251,8 @@@ batadv_tt_global_orig_entry_add(struct hlist_add_head_rcu(&orig_entry->list, &tt_global->orig_list); spin_unlock_bh(&tt_global->list_lock); + atomic_inc(&tt_global->orig_list_count); + out: if (orig_entry) batadv_tt_orig_list_entry_free_ref(orig_entry); @@@ -1277,7 -1311,7 +1311,7 @@@ static bool batadv_tt_global_add(struc goto out; common = &tt_global_entry->common; - memcpy(common->addr, tt_addr, ETH_ALEN); + ether_addr_copy(common->addr, tt_addr); common->vid = vid; common->flags = flags; @@@ -1292,6 -1326,7 +1326,7 @@@ common->added_at = jiffies; INIT_HLIST_HEAD(&tt_global_entry->orig_list); + atomic_set(&tt_global_entry->orig_list_count, 0); spin_lock_init(&tt_global_entry->list_lock); hash_added = batadv_hash_add(bat_priv->tt.global_hash, @@@ -1361,6 -1396,11 +1396,11 @@@ add_orig_entry ret = true; out_remove: + /* Do not remove multicast addresses from the local hash on + * global additions + */ + if (is_multicast_ether_addr(tt_addr)) + goto out; /* remove address from local hash if present */ local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid, @@@ -1552,6 -1592,25 +1592,25 @@@ out return 0; } + /** + * batadv_tt_global_del_orig_entry - remove and free an orig_entry + * @tt_global_entry: the global entry to remove the orig_entry from + * @orig_entry: the orig entry to remove and free + * + * Remove an orig_entry from its list in the given tt_global_entry and + * free this orig_entry afterwards. + */ + static void + batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry, + struct batadv_tt_orig_list_entry *orig_entry) + { + batadv_tt_global_size_dec(orig_entry->orig_node, + tt_global_entry->common.vid); + atomic_dec(&tt_global_entry->orig_list_count); + hlist_del_rcu(&orig_entry->list); + batadv_tt_orig_list_entry_free_ref(orig_entry); + } + /* deletes the orig list of a tt_global_entry */ static void batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry) @@@ -1562,20 -1621,26 +1621,26 @@@ spin_lock_bh(&tt_global_entry->list_lock); head = &tt_global_entry->orig_list; - hlist_for_each_entry_safe(orig_entry, safe, head, list) { - hlist_del_rcu(&orig_entry->list); - batadv_tt_global_size_dec(orig_entry->orig_node, - tt_global_entry->common.vid); - batadv_tt_orig_list_entry_free_ref(orig_entry); - } + hlist_for_each_entry_safe(orig_entry, safe, head, list) + batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry); spin_unlock_bh(&tt_global_entry->list_lock); } + /** + * batadv_tt_global_del_orig_node - remove orig_node from a global tt entry + * @bat_priv: the bat priv with all the soft interface information + * @tt_global_entry: the global entry to remove the orig_node from + * @orig_node: the originator announcing the client + * @message: message to append to the log on deletion + * + * Remove the given orig_node and its according orig_entry from the given + * global tt entry. + */ static void - batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, - struct batadv_tt_global_entry *tt_global_entry, - struct batadv_orig_node *orig_node, - const char *message) + batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv, + struct batadv_tt_global_entry *tt_global_entry, + struct batadv_orig_node *orig_node, + const char *message) { struct hlist_head *head; struct hlist_node *safe; @@@ -1592,10 -1657,8 +1657,8 @@@ orig_node->orig, tt_global_entry->common.addr, BATADV_PRINT_VID(vid), message); - hlist_del_rcu(&orig_entry->list); - batadv_tt_global_size_dec(orig_node, - tt_global_entry->common.vid); - batadv_tt_orig_list_entry_free_ref(orig_entry); + batadv_tt_global_del_orig_entry(tt_global_entry, + orig_entry); } } spin_unlock_bh(&tt_global_entry->list_lock); @@@ -1637,8 -1700,8 +1700,8 @@@ batadv_tt_global_del_roaming(struct bat /* there is another entry, we can simply delete this * one and can still use the other one. */ - batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, - orig_node, message); + batadv_tt_global_del_orig_node(bat_priv, tt_global_entry, + orig_node, message); } /** @@@ -1664,8 -1727,8 +1727,8 @@@ static void batadv_tt_global_del(struc goto out; if (!roaming) { - batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, - orig_node, message); + batadv_tt_global_del_orig_node(bat_priv, tt_global_entry, + orig_node, message); if (hlist_empty(&tt_global_entry->orig_list)) batadv_tt_global_free(bat_priv, tt_global_entry, @@@ -1748,8 -1811,8 +1811,8 @@@ void batadv_tt_global_del_orig(struct b struct batadv_tt_global_entry, common); - batadv_tt_global_del_orig_entry(bat_priv, tt_global, - orig_node, message); + batadv_tt_global_del_orig_node(bat_priv, tt_global, + orig_node, message); if (hlist_empty(&tt_global->orig_list)) { vid = tt_global->common.vid; @@@ -1763,7 -1826,7 +1826,7 @@@ } spin_unlock_bh(list_lock); } - orig_node->tt_initialised = false; + orig_node->capa_initialized &= ~BATADV_ORIG_CAPA_HAS_TT; } static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global, @@@ -2160,7 -2223,7 +2223,7 @@@ batadv_new_tt_req_node(struct batadv_pr if (!tt_req_node) goto unlock; - memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); + ether_addr_copy(tt_req_node->addr, orig_node->orig); tt_req_node->issued_at = jiffies; list_add(&tt_req_node->list, &bat_priv->tt.req_list); @@@ -2240,8 -2303,7 +2303,7 @@@ static void batadv_tt_tvlv_generate(str if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) continue; - memcpy(tt_change->addr, tt_common_entry->addr, - ETH_ALEN); + ether_addr_copy(tt_change->addr, tt_common_entry->addr); tt_change->flags = tt_common_entry->flags; tt_change->vid = htons(tt_common_entry->vid); memset(tt_change->reserved, 0, @@@ -2724,7 -2786,7 +2786,7 @@@ static void _batadv_tt_update_changes(s return; } } - orig_node->tt_initialised = true; + orig_node->capa_initialized |= BATADV_ORIG_CAPA_HAS_TT; } static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, @@@ -2932,7 -2994,7 +2994,7 @@@ static bool batadv_tt_check_roam_count( tt_roam_node->first_time = jiffies; atomic_set(&tt_roam_node->counter, BATADV_ROAMING_MAX_COUNT - 1); - memcpy(tt_roam_node->addr, client, ETH_ALEN); + ether_addr_copy(tt_roam_node->addr, client); list_add(&tt_roam_node->list, &bat_priv->tt.roam_list); ret = true; @@@ -3121,6 -3183,9 +3183,9 @@@ static void batadv_tt_local_purge_pendi */ static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv) { + /* Update multicast addresses in local translation table */ + batadv_mcast_mla_update(bat_priv); + if (atomic_read(&bat_priv->tt.local_changes) < 1) { if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) batadv_tt_tvlv_container_update(bat_priv); @@@ -3211,13 -3276,15 +3276,15 @@@ static void batadv_tt_update_orig(struc uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); struct batadv_tvlv_tt_vlan_data *tt_vlan; bool full_table = true; + bool has_tt_init; tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff; + has_tt_init = orig_node->capa_initialized & BATADV_ORIG_CAPA_HAS_TT; + /* orig table not initialised AND first diff is in the OGM OR the ttvn * increased by one -> we can apply the attached changes */ - if ((!orig_node->tt_initialised && ttvn == 1) || - ttvn - orig_ttvn == 1) { + if ((!has_tt_init && ttvn == 1) || ttvn - orig_ttvn == 1) { /* the OGM could not contain the changes due to their size or * because they have already been sent BATADV_TT_OGM_APPEND_MAX * times. @@@ -3257,7 -3324,7 +3324,7 @@@ /* if we missed more than one change or our tables are not * in sync anymore -> request fresh tt data */ - if (!orig_node->tt_initialised || ttvn != orig_ttvn || + if (!has_tt_init || ttvn != orig_ttvn || !batadv_tt_global_check_crc(orig_node, tt_vlan, tt_num_vlan)) { request_table: diff --combined net/batman-adv/translation-table.h index 20a1d78,ad84d7b..ad84d7b --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@@ -29,6 -29,8 +29,8 @@@ int batadv_tt_global_seq_print_text(str void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, int32_t match_vid, const char *message); + int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, + const uint8_t *addr, unsigned short vid); struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, const uint8_t *src, const uint8_t *addr, diff --combined net/batman-adv/types.h index 78370ab,d4b923c..d4b923c --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@@ -163,7 -163,7 +163,7 @@@ struct batadv_vlan_tt }; /** - * batadv_orig_node_vlan - VLAN specific data per orig_node + * struct batadv_orig_node_vlan - VLAN specific data per orig_node * @vid: the VLAN identifier * @tt: VLAN specific TT attributes * @list: list node for orig_node::vlan_list @@@ -204,14 -204,18 +204,18 @@@ struct batadv_orig_bat_iv * @batadv_dat_addr_t: address of the orig node in the distributed hash * @last_seen: time when last packet from this node was received * @bcast_seqno_reset: time when the broadcast seqno window was reset + * @mcast_flags: multicast flags announced by the orig node + * @mcast_want_all_unsnoop_node: a list node for the + * mcast.want_all_unsnoopables list + * @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list + * @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list * @capabilities: announced capabilities of this originator + * @capa_initialized: bitfield to remember whether a capability was initialized * @last_ttvn: last seen translation table version number * @tt_buff: last tt changeset this node received from the orig node * @tt_buff_len: length of the last tt changeset this node received from the * orig node * @tt_buff_lock: lock that protects tt_buff and tt_buff_len - * @tt_initialised: bool keeping track of whether or not this node have received - * any translation table information from the orig node yet * @tt_lock: prevents from updating the table while reading it. Table update is * made up by two operations (data structure update and metdata -CRC/TTVN- * recalculation) and they have to be executed atomically in order to avoid @@@ -247,12 -251,18 +251,18 @@@ struct batadv_orig_node #endif unsigned long last_seen; unsigned long bcast_seqno_reset; + #ifdef CONFIG_BATMAN_ADV_MCAST + uint8_t mcast_flags; + struct hlist_node mcast_want_all_unsnoopables_node; + struct hlist_node mcast_want_all_ipv4_node; + struct hlist_node mcast_want_all_ipv6_node; + #endif uint8_t capabilities; + uint8_t capa_initialized; atomic_t last_ttvn; unsigned char *tt_buff; int16_t tt_buff_len; spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ - bool tt_initialised; /* prevents from changing the table while reading it */ spinlock_t tt_lock; DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); @@@ -282,10 -292,15 +292,15 @@@ * enum batadv_orig_capabilities - orig node capabilities * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled + * @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability + * @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability + * (= orig node announces a tvlv of type BATADV_TVLV_MCAST) */ enum batadv_orig_capabilities { BATADV_ORIG_CAPA_HAS_DAT = BIT(0), BATADV_ORIG_CAPA_HAS_NC = BIT(1), + BATADV_ORIG_CAPA_HAS_TT = BIT(2), + BATADV_ORIG_CAPA_HAS_MCAST = BIT(3), }; /** @@@ -334,7 -349,7 +349,7 @@@ struct batadv_neigh_node }; /** - * struct batadv_neigh_node_bat_iv - neighbor information per outgoing + * struct batadv_neigh_ifinfo_bat_iv - neighbor information per outgoing * interface for BATMAN IV * @tq_recv: ring buffer of received TQ values from this neigh node * @tq_index: ring buffer index @@@ -544,7 -559,7 +559,7 @@@ struct batadv_priv_bla #endif /** - * struct batadv_debug_log - debug logging data + * struct batadv_priv_debug_log - debug logging data * @log_buff: buffer holding the logs (ring bufer) * @log_start: index of next character to read * @log_end: index of next character to write @@@ -607,6 -622,39 +622,39 @@@ struct batadv_priv_dat }; #endif + #ifdef CONFIG_BATMAN_ADV_MCAST + /** + * struct batadv_priv_mcast - per mesh interface mcast data + * @mla_list: list of multicast addresses we are currently announcing via TT + * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable + * multicast traffic + * @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic + * @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic + * @flags: the flags we have last sent in our mcast tvlv + * @enabled: whether the multicast tvlv is currently enabled + * @num_disabled: number of nodes that have no mcast tvlv + * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic + * @num_want_all_ipv4: counter for items in want_all_ipv4_list + * @num_want_all_ipv6: counter for items in want_all_ipv6_list + * @want_lists_lock: lock for protecting modifications to mcast want lists + * (traversals are rcu-locked) + */ + struct batadv_priv_mcast { + struct hlist_head mla_list; + struct hlist_head want_all_unsnoopables_list; + struct hlist_head want_all_ipv4_list; + struct hlist_head want_all_ipv6_list; + uint8_t flags; + bool enabled; + atomic_t num_disabled; + atomic_t num_want_all_unsnoopables; + atomic_t num_want_all_ipv4; + atomic_t num_want_all_ipv6; + /* protects want_all_{unsnoopables,ipv4,ipv6}_list */ + spinlock_t want_lists_lock; + }; + #endif + /** * struct batadv_priv_nc - per mesh interface network coding private data * @work: work queue callback item for cleanup @@@ -672,6 -720,8 +720,8 @@@ struct batadv_softif_vlan * enabled * @distributed_arp_table: bool indicating whether distributed ARP table is * enabled + * @multicast_mode: Enable or disable multicast optimizations on this node's + * sender/originating side * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) * @gw_sel_class: gateway selection class (applies if gw_mode client) * @orig_interval: OGM broadcast interval in milliseconds @@@ -702,6 -752,7 +752,7 @@@ * @tt: translation table data * @tvlv: type-version-length-value data * @dat: distributed arp table data + * @mcast: multicast data * @network_coding: bool indicating whether network coding is enabled * @batadv_priv_nc: network coding data */ @@@ -721,6 -772,9 +772,9 @@@ struct batadv_priv #ifdef CONFIG_BATMAN_ADV_DAT atomic_t distributed_arp_table; #endif + #ifdef CONFIG_BATMAN_ADV_MCAST + atomic_t multicast_mode; + #endif atomic_t gw_mode; atomic_t gw_sel_class; atomic_t orig_interval; @@@ -759,6 -813,9 +813,9 @@@ #ifdef CONFIG_BATMAN_ADV_DAT struct batadv_priv_dat dat; #endif + #ifdef CONFIG_BATMAN_ADV_MCAST + struct batadv_priv_mcast mcast; + #endif #ifdef CONFIG_BATMAN_ADV_NC atomic_t network_coding; struct batadv_priv_nc nc; @@@ -881,12 -938,14 +938,14 @@@ struct batadv_tt_local_entry * struct batadv_tt_global_entry - translation table global entry data * @common: general translation table data * @orig_list: list of orig nodes announcing this non-mesh client + * @orig_list_count: number of items in the orig_list * @list_lock: lock protecting orig_list * @roam_at: time at which TT_GLOBAL_ROAM was set */ struct batadv_tt_global_entry { struct batadv_tt_common_entry common; struct hlist_head orig_list; + atomic_t orig_list_count; spinlock_t list_lock; /* protects orig_list */ unsigned long roam_at; }; @@@ -1004,8 -1063,8 +1063,8 @@@ struct batadv_nc_packet }; /** - * batadv_skb_cb - control buffer structure used to store private data relevant - * to batman-adv in the skb->cb buffer in skbs. + * struct batadv_skb_cb - control buffer structure used to store private data + * relevant to batman-adv in the skb->cb buffer in skbs. * @decoded: Marks a skb as decoded, which is checked when searching for coding * opportunities in network-coding.c */ @@@ -1116,6 -1175,16 +1175,16 @@@ struct batadv_dat_entry }; /** + * struct batadv_hw_addr - a list entry for a MAC address + * @list: list node for the linking of entries + * @addr: the MAC address of this list entry + */ + struct batadv_hw_addr { + struct hlist_node list; + unsigned char addr[ETH_ALEN]; + }; + + /** * struct batadv_dat_candidate - candidate destination for DAT operations * @type: the type of the selected candidate. It can one of the following: * - BATADV_DAT_CANDIDATE_NOT_FOUND -- linux integration
9 years, 1 month
1
0
0
0
[linux-merge]linux integration; branch, merge/master, updated. v3.13-rc1-2058-ga97ec89
by postmaster@open-mesh.org
The following commit has been merged in the merge/master branch: commit a97ec892afc89d1b81cd8934697f47b3ee4efd10 Merge: 669cbd55edae689ce151bc17860f9cd236b72c5e d80561222893dfca2bbf32dc75a697fd24bbf14e Author: Antonio Quartulli <antonio(a)meshcoding.com> Date: Sat Feb 15 21:04:59 2014 +0100 Merge commit 'd80561222893dfca2bbf32dc75a697fd24bbf14e' into merge/master Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com> Conflicts: net/batman-adv/compat.h diff --combined net/batman-adv/bat_iv_ogm.c index 512159b,8323bce..8323bce --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@@ -241,19 -241,19 +241,19 @@@ batadv_iv_ogm_orig_get(struct batadv_pr size = bat_priv->num_ifaces * sizeof(uint8_t); orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC); if (!orig_node->bat_iv.bcast_own_sum) - goto free_bcast_own; + goto free_orig_node; hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig, batadv_choose_orig, orig_node, &orig_node->hash_entry); if (hash_added != 0) - goto free_bcast_own; + goto free_orig_node; return orig_node; - free_bcast_own: - kfree(orig_node->bat_iv.bcast_own); free_orig_node: + /* free twice, as batadv_orig_node_new sets refcount to 2 */ + batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node); return NULL; @@@ -266,7 -266,7 +266,7 @@@ batadv_iv_ogm_neigh_new(struct batadv_h struct batadv_orig_node *orig_neigh) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); - struct batadv_neigh_node *neigh_node; + struct batadv_neigh_node *neigh_node, *tmp_neigh_node; neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node); if (!neigh_node) @@@ -281,14 -281,24 +281,24 @@@ neigh_node->orig_node = orig_neigh; neigh_node->if_incoming = hard_iface; - batadv_dbg(BATADV_DBG_BATMAN, bat_priv, - "Creating new neighbor %pM for orig_node %pM on interface %s\n", - neigh_addr, orig_node->orig, hard_iface->net_dev->name); - spin_lock_bh(&orig_node->neigh_list_lock); - hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); + tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface, + neigh_addr); + if (!tmp_neigh_node) { + hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); + } else { + kfree(neigh_node); + batadv_hardif_free_ref(hard_iface); + neigh_node = tmp_neigh_node; + } spin_unlock_bh(&orig_node->neigh_list_lock); + if (!tmp_neigh_node) + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, + "Creating new neighbor %pM for orig_node %pM on interface %s\n", + neigh_addr, orig_node->orig, + hard_iface->net_dev->name); + out: return neigh_node; } diff --combined net/batman-adv/distributed-arp-table.c index edee504,5bb37a8..5bb37a8 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@@ -1027,6 -1027,11 +1027,11 @@@ bool batadv_dat_snoop_incoming_arp_requ 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); diff --combined net/batman-adv/hard-interface.c index 1b12573,b851cc5..b851cc5 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@@ -87,15 -87,13 +87,13 @@@ static bool batadv_is_on_batman_iface(c return false; /* recurse over the parent device */ - parent_dev = dev_get_by_index(&init_net, net_dev->iflink); + parent_dev = __dev_get_by_index(&init_net, net_dev->iflink); /* if we got a NULL parent_dev there is something broken.. */ if (WARN(!parent_dev, "Cannot find parent device")) return false; ret = batadv_is_on_batman_iface(parent_dev); - if (parent_dev) - dev_put(parent_dev); return ret; } @@@ -243,7 -241,7 +241,7 @@@ int batadv_hardif_min_mtu(struct net_de { struct batadv_priv *bat_priv = netdev_priv(soft_iface); const struct batadv_hard_iface *hard_iface; - int min_mtu = ETH_DATA_LEN; + int min_mtu = INT_MAX; rcu_read_lock(); list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { @@@ -258,8 -256,6 +256,6 @@@ } rcu_read_unlock(); - atomic_set(&bat_priv->packet_size_max, min_mtu); - if (atomic_read(&bat_priv->fragmentation) == 0) goto out; @@@ -270,13 -266,21 +266,21 @@@ min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE); min_mtu -= sizeof(struct batadv_frag_packet); min_mtu *= BATADV_FRAG_MAX_FRAGMENTS; - atomic_set(&bat_priv->packet_size_max, min_mtu); - - /* with fragmentation enabled we can fragment external packets easily */ - min_mtu = min_t(int, min_mtu, ETH_DATA_LEN); out: - return min_mtu - batadv_max_header_len(); + /* report to the other components the maximum amount of bytes that + * batman-adv can send over the wire (without considering the payload + * overhead). For example, this value is used by TT to compute the + * maximum local table table size + */ + atomic_set(&bat_priv->packet_size_max, min_mtu); + + /* the real soft-interface MTU is computed by removing the payload + * overhead from the maximum amount of bytes that was just computed. + * + * However batman-adv does not support MTUs bigger than ETH_DATA_LEN + */ + return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN); } /* adjusts the MTU if a new interface with a smaller MTU appeared. */ diff --combined net/batman-adv/originator.c index 6df12a2,8539416..8539416 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@@ -458,6 -458,42 +458,42 @@@ out } /** + * batadv_neigh_node_get - retrieve a neighbour from the list + * @orig_node: originator which the neighbour belongs to + * @hard_iface: the interface where this neighbour is connected to + * @addr: the address of the neighbour + * + * Looks for and possibly returns a neighbour belonging to this originator list + * which is connected through the provided hard interface. + * Returns NULL if the neighbour is not found. + */ + struct batadv_neigh_node * + batadv_neigh_node_get(const struct batadv_orig_node *orig_node, + const struct batadv_hard_iface *hard_iface, + const uint8_t *addr) + { + struct batadv_neigh_node *tmp_neigh_node, *res = NULL; + + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) { + if (!batadv_compare_eth(tmp_neigh_node->addr, addr)) + continue; + + if (tmp_neigh_node->if_incoming != hard_iface) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + res = tmp_neigh_node; + break; + } + rcu_read_unlock(); + + return res; + } + + /** * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object * @rcu: rcu pointer of the orig_ifinfo object */ diff --combined net/batman-adv/originator.h index 37be290,db3a9ed..db3a9ed --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@@ -29,6 -29,10 +29,10 @@@ void batadv_orig_node_free_ref_now(stru struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, const uint8_t *addr); struct batadv_neigh_node * + batadv_neigh_node_get(const struct batadv_orig_node *orig_node, + const struct batadv_hard_iface *hard_iface, + const uint8_t *addr); + struct batadv_neigh_node * batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, const uint8_t *neigh_addr, struct batadv_orig_node *orig_node); diff --combined net/batman-adv/routing.c index 1ed9f7c,a953d5b..a953d5b --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@@ -688,7 -688,7 +688,7 @@@ static int batadv_check_unicast_ttvn(st int is_old_ttvn; /* check if there is enough data before accessing it */ - if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0) + if (!pskb_may_pull(skb, hdr_len + ETH_HLEN)) return 0; /* create a copy of the skb (in case of for re-routing) to modify it. */ @@@ -918,6 -918,8 +918,8 @@@ int batadv_recv_unicast_tvlv(struct sk_ if (ret != NET_RX_SUCCESS) ret = batadv_route_unicast_packet(skb, recv_if); + else + consume_skb(skb); return ret; } diff --combined net/batman-adv/send.c index 579f5f0,1703a2e..1703a2e --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@@ -254,7 -254,7 +254,7 @@@ static int batadv_send_skb_unicast(stru struct batadv_orig_node *orig_node, unsigned short vid) { - struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct ethhdr *ethhdr; struct batadv_unicast_packet *unicast_packet; int ret = NET_XMIT_DROP; @@@ -279,6 -279,10 +279,10 @@@ goto out; } + /* skb->data might have been reallocated by + * batadv_send_skb_prepare_unicast{,_4addr}() + */ + ethhdr = eth_hdr(skb); unicast_packet = (struct batadv_unicast_packet *)skb->data; /* inform the destination node that we are still missing a correct route diff --combined net/batman-adv/translation-table.c index b6071f6,959dde7..959dde7 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@@ -1975,6 -1975,7 +1975,7 @@@ static uint32_t batadv_tt_global_crc(st struct hlist_head *head; uint32_t i, crc_tmp, crc = 0; uint8_t flags; + __be16 tmp_vid; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@@ -2011,8 -2012,11 +2012,11 @@@ orig_node)) continue; - crc_tmp = crc32c(0, &tt_common->vid, - sizeof(tt_common->vid)); + /* use network order to read the VID: this ensures that + * every node reads the bytes in the same order. + */ + tmp_vid = htons(tt_common->vid); + crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); /* compute the CRC on flags that have to be kept in sync * among nodes @@@ -2046,6 -2050,7 +2050,7 @@@ static uint32_t batadv_tt_local_crc(str struct hlist_head *head; uint32_t i, crc_tmp, crc = 0; uint8_t flags; + __be16 tmp_vid; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@@ -2064,8 -2069,11 +2069,11 @@@ if (tt_common->flags & BATADV_TT_CLIENT_NEW) continue; - crc_tmp = crc32c(0, &tt_common->vid, - sizeof(tt_common->vid)); + /* use network order to read the VID: this ensures that + * every node reads the bytes in the same order. + */ + tmp_vid = htons(tt_common->vid); + crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); /* compute the CRC on flags that have to be kept in sync * among nodes @@@ -2262,6 -2270,7 +2270,7 @@@ static bool batadv_tt_global_check_crc( { struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; struct batadv_orig_node_vlan *vlan; + uint32_t crc; int i; /* check if each received CRC matches the locally stored one */ @@@ -2281,7 -2290,10 +2290,10 @@@ if (!vlan) return false; - if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc)) + crc = vlan->tt.crc; + batadv_orig_node_vlan_free_ref(vlan); + + if (crc != ntohl(tt_vlan_tmp->crc)) return false; } @@@ -3218,7 -3230,6 +3230,6 @@@ static void batadv_tt_update_orig(struc spin_lock_bh(&orig_node->tt_lock); - tt_change = (struct batadv_tvlv_tt_change *)tt_buff; batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn, tt_change); -- linux integration
9 years, 1 month
1
0
0
0
[batman-adv] master: batman-adv: use ether_addr_copy instead of memcpy in multicast code (fb4756f)
by postmaster@open-mesh.org
Repository : ssh://git@open-mesh.org/batman-adv On branch : master >--------------------------------------------------------------- commit fb4756fe5f6e58ca2ab208ca634ae4c8dd6e9499 Author: Linus Lüssing <linus.luessing(a)web.de> Date: Tue Feb 18 09:14:05 2014 +0100 batman-adv: use ether_addr_copy instead of memcpy in multicast code ether_addr_copy is supposed to be slightly more efficient for copying mac addresses, so let's use it. This makes recent versions of checkpatch happy, too. Introduced by e368857f66620b8483166e8e6556d9c87f9b3e71 ("batman-adv: Multicast Listener Announcements via Translation Table") Reported-by: Antonio Quartulli <antonio(a)meshcoding.com> Signed-off-by: Linus Lüssing <linus.luessing(a)web.de> Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch> >--------------------------------------------------------------- fb4756fe5f6e58ca2ab208ca634ae4c8dd6e9499 multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multicast.c b/multicast.c index 00bb30e..e69143b 100644 --- a/multicast.c +++ b/multicast.c @@ -45,7 +45,7 @@ static int batadv_mcast_mla_softif_get(struct net_device *dev, break; } - memcpy(&new->addr, &mc_list_entry->addr, ETH_ALEN); + ether_addr_copy(&new->addr, &mc_list_entry->addr); hlist_add_head(&new->list, mcast_list); ret++; }
9 years, 1 month
1
0
0
0
[batman-adv] master's head updated: Merge branch 'next' (3a3f7b9)
by postmaster@open-mesh.org
Repository : ssh://git@open-mesh.org/batman-adv Branch 'master' now includes: 15fb0fa batman-adv add compat code for consume_skb 73ae494 Merge branch 'maint' into next 3a3f7b9 Merge branch 'next'
9 years, 1 month
1
0
0
0
[batman-adv] master: Merge branch 'next' (3a3f7b9)
by postmaster@open-mesh.org
Repository : ssh://git@open-mesh.org/batman-adv On branch : master >--------------------------------------------------------------- commit 3a3f7b9d9627a9dc7fcf10221d617ccb32c72125 Merge: 534aa4a 73ae494 Author: Marek Lindner <mareklindner(a)neomailbox.ch> Date: Thu Feb 20 18:55:44 2014 +0800 Merge branch 'next' >--------------------------------------------------------------- 3a3f7b9d9627a9dc7fcf10221d617ccb32c72125 compat.h | 2 ++ 1 file changed, 2 insertions(+)
9 years, 1 month
1
0
0
0
[batman-adv] next's head updated: Merge branch 'maint' into next (73ae494)
by postmaster@open-mesh.org
Repository : ssh://git@open-mesh.org/batman-adv Branch 'next' now includes: 15fb0fa batman-adv add compat code for consume_skb 73ae494 Merge branch 'maint' into next
9 years, 1 month
1
0
0
0
[batman-adv] next: Merge branch 'maint' into next (73ae494)
by postmaster@open-mesh.org
Repository : ssh://git@open-mesh.org/batman-adv On branch : next >--------------------------------------------------------------- commit 73ae49487a464fd75fdfd09483259b29cfe7255e Merge: 28d69c6 15fb0fa Author: Marek Lindner <mareklindner(a)neomailbox.ch> Date: Thu Feb 20 18:54:49 2014 +0800 Merge branch 'maint' into next >--------------------------------------------------------------- 73ae49487a464fd75fdfd09483259b29cfe7255e compat.h | 2 ++ 1 file changed, 2 insertions(+)
9 years, 1 month
1
0
0
0
[batman-adv] maint: batman-adv add compat code for consume_skb (15fb0fa)
by postmaster@open-mesh.org
Repository : ssh://git@open-mesh.org/batman-adv On branch : maint >--------------------------------------------------------------- commit 15fb0fab51a3695738f65dfaab045e979fc89dce Author: Antonio Quartulli <antonio(a)meshcoding.com> Date: Mon Feb 17 09:29:32 2014 +0100 batman-adv add compat code for consume_skb consume_skb() has been implemented in 2.6.30, therefore some some compat code is needed for 2.6.29. This patch adds it. Introduced by 9289542085d7e298b90c7b6fb6efb509dab69d8b ("batman-adv: free skb on TVLV parsing success") Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com> Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch> >--------------------------------------------------------------- 15fb0fab51a3695738f65dfaab045e979fc89dce compat.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compat.h b/compat.h index deea92b..94407a6 100644 --- a/compat.h +++ b/compat.h @@ -26,6 +26,8 @@ #include <linux/version.h> /* LINUX_VERSION_CODE */ +#define consume_skb(_skb) kfree_skb(_skb) + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) #undef __alloc_percpu
9 years, 1 month
1
0
0
0
[batman-adv] master: batman-adv: make the use of braces in if-else consistent (534aa4a)
by postmaster@open-mesh.org
Repository : ssh://git@open-mesh.org/batman-adv On branch : master >--------------------------------------------------------------- commit 534aa4a53c8c63e008b4a2470113f0f50c9f0d16 Author: Martin Hundebøll <martin(a)hundeboll.net> Date: Tue Feb 18 12:03:55 2014 +0100 batman-adv: make the use of braces in if-else consistent To avoid confusion, the linux kernel coding style discourage the use of one if-else branch with braces and another without braces. Introduced-by: 65d8217193427026169c48112c561c5ca4d1bd18 ("batman-adv: compat: fix null pointer exception for kernels < 3.9") Signed-off-by: Martin Hundebøll <martin(a)hundeboll.net> Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch> >--------------------------------------------------------------- 534aa4a53c8c63e008b4a2470113f0f50c9f0d16 compat.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compat.h b/compat.h index 7beba36..0ceb2b1 100644 --- a/compat.h +++ b/compat.h @@ -167,8 +167,9 @@ static inline int batadv_param_set_copystring(const char *val, rcu_read_unlock(); \ dev_hold(dev); \ return dev; \ - } else \ - dev = NULL; + } else {\ + dev = NULL; \ + } #endif /* < KERNEL_VERSION(2, 6, 36) */
9 years, 1 month
1
0
0
0
← Newer
1
2
3
4
5
6
7
Older →
Jump to page:
1
2
3
4
5
6
7
Results per page:
10
25
50
100
200