diff options
-rw-r--r-- | net/batman-adv/distributed-arp-table.c | 265 | ||||
-rw-r--r-- | net/batman-adv/distributed-arp-table.h | 11 | ||||
-rw-r--r-- | net/batman-adv/main.h | 2 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 29 | ||||
-rw-r--r-- | net/batman-adv/send.c | 4 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 16 |
6 files changed, 325 insertions, 2 deletions
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 49a213ce2aac..f43bf8e4a2b7 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/if_ether.h> | 20 | #include <linux/if_ether.h> |
21 | #include <linux/if_arp.h> | 21 | #include <linux/if_arp.h> |
22 | #include <net/arp.h> | ||
22 | 23 | ||
23 | #include "main.h" | 24 | #include "main.h" |
24 | #include "hash.h" | 25 | #include "hash.h" |
@@ -27,6 +28,7 @@ | |||
27 | #include "originator.h" | 28 | #include "originator.h" |
28 | #include "send.h" | 29 | #include "send.h" |
29 | #include "types.h" | 30 | #include "types.h" |
31 | #include "translation-table.h" | ||
30 | #include "unicast.h" | 32 | #include "unicast.h" |
31 | 33 | ||
32 | static void batadv_dat_purge(struct work_struct *work); | 34 | static void batadv_dat_purge(struct work_struct *work); |
@@ -766,3 +768,266 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, | |||
766 | out: | 768 | out: |
767 | return type; | 769 | return type; |
768 | } | 770 | } |
771 | |||
772 | /** | ||
773 | * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to | ||
774 | * answer using DAT | ||
775 | * @bat_priv: the bat priv with all the soft interface information | ||
776 | * @skb: packet to check | ||
777 | * | ||
778 | * Returns true if the message has been sent to the dht candidates, false | ||
779 | * otherwise. In case of true the message has to be enqueued to permit the | ||
780 | * fallback | ||
781 | */ | ||
782 | bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | ||
783 | struct sk_buff *skb) | ||
784 | { | ||
785 | uint16_t type = 0; | ||
786 | __be32 ip_dst, ip_src; | ||
787 | uint8_t *hw_src; | ||
788 | bool ret = false; | ||
789 | struct batadv_dat_entry *dat_entry = NULL; | ||
790 | struct sk_buff *skb_new; | ||
791 | struct batadv_hard_iface *primary_if = NULL; | ||
792 | |||
793 | type = batadv_arp_get_type(bat_priv, skb, 0); | ||
794 | /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast | ||
795 | * message to the selected DHT candidates | ||
796 | */ | ||
797 | if (type != ARPOP_REQUEST) | ||
798 | goto out; | ||
799 | |||
800 | batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REQUEST"); | ||
801 | |||
802 | ip_src = batadv_arp_ip_src(skb, 0); | ||
803 | hw_src = batadv_arp_hw_src(skb, 0); | ||
804 | ip_dst = batadv_arp_ip_dst(skb, 0); | ||
805 | |||
806 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
807 | |||
808 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | ||
809 | if (dat_entry) { | ||
810 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
811 | if (!primary_if) | ||
812 | goto out; | ||
813 | |||
814 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, | ||
815 | primary_if->soft_iface, ip_dst, hw_src, | ||
816 | dat_entry->mac_addr, hw_src); | ||
817 | if (!skb_new) | ||
818 | goto out; | ||
819 | |||
820 | skb_reset_mac_header(skb_new); | ||
821 | skb_new->protocol = eth_type_trans(skb_new, | ||
822 | primary_if->soft_iface); | ||
823 | bat_priv->stats.rx_packets++; | ||
824 | bat_priv->stats.rx_bytes += skb->len + ETH_HLEN; | ||
825 | primary_if->soft_iface->last_rx = jiffies; | ||
826 | |||
827 | netif_rx(skb_new); | ||
828 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n"); | ||
829 | ret = true; | ||
830 | } else { | ||
831 | /* Send the request on the DHT */ | ||
832 | ret = batadv_dat_send_data(bat_priv, skb, ip_dst, | ||
833 | BATADV_P_DAT_DHT_GET); | ||
834 | } | ||
835 | out: | ||
836 | if (dat_entry) | ||
837 | batadv_dat_entry_free_ref(dat_entry); | ||
838 | if (primary_if) | ||
839 | batadv_hardif_free_ref(primary_if); | ||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | /** | ||
844 | * batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to | ||
845 | * answer using the local DAT storage | ||
846 | * @bat_priv: the bat priv with all the soft interface information | ||
847 | * @skb: packet to check | ||
848 | * @hdr_size: size of the encapsulation header | ||
849 | * | ||
850 | * Returns true if the request has been answered, false otherwise | ||
851 | */ | ||
852 | bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, | ||
853 | struct sk_buff *skb, int hdr_size) | ||
854 | { | ||
855 | uint16_t type; | ||
856 | __be32 ip_src, ip_dst; | ||
857 | uint8_t *hw_src; | ||
858 | struct sk_buff *skb_new; | ||
859 | struct batadv_hard_iface *primary_if = NULL; | ||
860 | struct batadv_dat_entry *dat_entry = NULL; | ||
861 | bool ret = false; | ||
862 | int err; | ||
863 | |||
864 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); | ||
865 | if (type != ARPOP_REQUEST) | ||
866 | goto out; | ||
867 | |||
868 | hw_src = batadv_arp_hw_src(skb, hdr_size); | ||
869 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
870 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
871 | |||
872 | batadv_dbg_arp(bat_priv, skb, type, hdr_size, | ||
873 | "Parsing incoming ARP REQUEST"); | ||
874 | |||
875 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
876 | |||
877 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | ||
878 | if (!dat_entry) | ||
879 | goto out; | ||
880 | |||
881 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
882 | if (!primary_if) | ||
883 | goto out; | ||
884 | |||
885 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, | ||
886 | primary_if->soft_iface, ip_dst, hw_src, | ||
887 | dat_entry->mac_addr, hw_src); | ||
888 | |||
889 | if (!skb_new) | ||
890 | goto out; | ||
891 | |||
892 | /* to preserve backwards compatibility, here the node has to answer | ||
893 | * using the same packet type it received for the request. This is due | ||
894 | * to that if a node is not using the 4addr packet format it may not | ||
895 | * support it. | ||
896 | */ | ||
897 | if (hdr_size == sizeof(struct batadv_unicast_4addr_packet)) | ||
898 | err = batadv_unicast_4addr_send_skb(bat_priv, skb_new, | ||
899 | BATADV_P_DAT_CACHE_REPLY); | ||
900 | else | ||
901 | err = batadv_unicast_send_skb(bat_priv, skb_new); | ||
902 | |||
903 | if (!err) | ||
904 | ret = true; | ||
905 | out: | ||
906 | if (dat_entry) | ||
907 | batadv_dat_entry_free_ref(dat_entry); | ||
908 | if (primary_if) | ||
909 | batadv_hardif_free_ref(primary_if); | ||
910 | if (ret) | ||
911 | kfree_skb(skb); | ||
912 | return ret; | ||
913 | } | ||
914 | |||
915 | /** | ||
916 | * batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT | ||
917 | * @bat_priv: the bat priv with all the soft interface information | ||
918 | * @skb: packet to check | ||
919 | */ | ||
920 | void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | ||
921 | struct sk_buff *skb) | ||
922 | { | ||
923 | uint16_t type; | ||
924 | __be32 ip_src, ip_dst; | ||
925 | uint8_t *hw_src, *hw_dst; | ||
926 | |||
927 | type = batadv_arp_get_type(bat_priv, skb, 0); | ||
928 | if (type != ARPOP_REPLY) | ||
929 | return; | ||
930 | |||
931 | batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REPLY"); | ||
932 | |||
933 | hw_src = batadv_arp_hw_src(skb, 0); | ||
934 | ip_src = batadv_arp_ip_src(skb, 0); | ||
935 | hw_dst = batadv_arp_hw_dst(skb, 0); | ||
936 | ip_dst = batadv_arp_ip_dst(skb, 0); | ||
937 | |||
938 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
939 | batadv_dat_entry_add(bat_priv, ip_dst, hw_dst); | ||
940 | |||
941 | /* Send the ARP reply to the candidates for both the IP addresses that | ||
942 | * the node got within the ARP reply | ||
943 | */ | ||
944 | batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT); | ||
945 | batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT); | ||
946 | } | ||
947 | /** | ||
948 | * batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local | ||
949 | * DAT storage only | ||
950 | * @bat_priv: the bat priv with all the soft interface information | ||
951 | * @skb: packet to check | ||
952 | * @hdr_size: siaze of the encapsulation header | ||
953 | */ | ||
954 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | ||
955 | struct sk_buff *skb, int hdr_size) | ||
956 | { | ||
957 | uint16_t type; | ||
958 | __be32 ip_src, ip_dst; | ||
959 | uint8_t *hw_src, *hw_dst; | ||
960 | bool ret = false; | ||
961 | |||
962 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); | ||
963 | if (type != ARPOP_REPLY) | ||
964 | goto out; | ||
965 | |||
966 | batadv_dbg_arp(bat_priv, skb, type, hdr_size, | ||
967 | "Parsing incoming ARP REPLY"); | ||
968 | |||
969 | hw_src = batadv_arp_hw_src(skb, hdr_size); | ||
970 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
971 | hw_dst = batadv_arp_hw_dst(skb, hdr_size); | ||
972 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
973 | |||
974 | /* Update our internal cache with both the IP addresses the node got | ||
975 | * within the ARP reply | ||
976 | */ | ||
977 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
978 | batadv_dat_entry_add(bat_priv, ip_dst, hw_dst); | ||
979 | |||
980 | /* if this REPLY is directed to a client of mine, let's deliver the | ||
981 | * packet to the interface | ||
982 | */ | ||
983 | ret = !batadv_is_my_client(bat_priv, hw_dst); | ||
984 | out: | ||
985 | /* if ret == false -> packet has to be delivered to the interface */ | ||
986 | return ret; | ||
987 | } | ||
988 | |||
989 | /** | ||
990 | * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped | ||
991 | * (because the node has already got the reply via DAT) or not | ||
992 | * @bat_priv: the bat priv with all the soft interface information | ||
993 | * @forw_packet: the broadcast packet | ||
994 | * | ||
995 | * Returns true if the node can drop the packet, false otherwise | ||
996 | */ | ||
997 | bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, | ||
998 | struct batadv_forw_packet *forw_packet) | ||
999 | { | ||
1000 | uint16_t type; | ||
1001 | __be32 ip_dst; | ||
1002 | struct batadv_dat_entry *dat_entry = NULL; | ||
1003 | bool ret = false; | ||
1004 | const size_t bcast_len = sizeof(struct batadv_bcast_packet); | ||
1005 | |||
1006 | /* If this packet is an ARP_REQUEST and the node already has the | ||
1007 | * information that it is going to ask, then the packet can be dropped | ||
1008 | */ | ||
1009 | if (forw_packet->num_packets) | ||
1010 | goto out; | ||
1011 | |||
1012 | type = batadv_arp_get_type(bat_priv, forw_packet->skb, bcast_len); | ||
1013 | if (type != ARPOP_REQUEST) | ||
1014 | goto out; | ||
1015 | |||
1016 | ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len); | ||
1017 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | ||
1018 | /* check if the node already got this entry */ | ||
1019 | if (!dat_entry) { | ||
1020 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
1021 | "ARP Request for %pI4: fallback\n", &ip_dst); | ||
1022 | goto out; | ||
1023 | } | ||
1024 | |||
1025 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
1026 | "ARP Request for %pI4: fallback prevented\n", &ip_dst); | ||
1027 | ret = true; | ||
1028 | |||
1029 | out: | ||
1030 | if (dat_entry) | ||
1031 | batadv_dat_entry_free_ref(dat_entry); | ||
1032 | return ret; | ||
1033 | } | ||
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index f4e282a6e634..01308cea5b4e 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h | |||
@@ -27,6 +27,17 @@ | |||
27 | 27 | ||
28 | #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) | 28 | #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) |
29 | 29 | ||
30 | bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | ||
31 | struct sk_buff *skb); | ||
32 | bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, | ||
33 | struct sk_buff *skb, int hdr_size); | ||
34 | void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | ||
35 | struct sk_buff *skb); | ||
36 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | ||
37 | struct sk_buff *skb, int hdr_size); | ||
38 | bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, | ||
39 | struct batadv_forw_packet *forw_packet); | ||
40 | |||
30 | /** | 41 | /** |
31 | * batadv_dat_init_orig_node_addr - assign a DAT address to the orig_node | 42 | * batadv_dat_init_orig_node_addr - assign a DAT address to the orig_node |
32 | * @orig_node: the node to assign the DAT address to | 43 | * @orig_node: the node to assign the DAT address to |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 25adfd29cc92..240c74ffeb93 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -74,6 +74,8 @@ | |||
74 | 74 | ||
75 | #define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ | 75 | #define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ |
76 | 76 | ||
77 | /* msecs after which an ARP_REQUEST is sent in broadcast as fallback */ | ||
78 | #define ARP_REQ_DELAY 250 | ||
77 | /* numbers of originator to contact for any PUT/GET DHT operation */ | 79 | /* numbers of originator to contact for any PUT/GET DHT operation */ |
78 | #define BATADV_DAT_CANDIDATES_NUM 3 | 80 | #define BATADV_DAT_CANDIDATES_NUM 3 |
79 | 81 | ||
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 859679b08286..1826699314b7 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "vis.h" | 28 | #include "vis.h" |
29 | #include "unicast.h" | 29 | #include "unicast.h" |
30 | #include "bridge_loop_avoidance.h" | 30 | #include "bridge_loop_avoidance.h" |
31 | #include "distributed-arp-table.h" | ||
31 | 32 | ||
32 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 33 | static int batadv_route_unicast_packet(struct sk_buff *skb, |
33 | struct batadv_hard_iface *recv_if); | 34 | struct batadv_hard_iface *recv_if); |
@@ -985,11 +986,13 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
985 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 986 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
986 | struct batadv_unicast_packet *unicast_packet; | 987 | struct batadv_unicast_packet *unicast_packet; |
987 | int hdr_size = sizeof(*unicast_packet); | 988 | int hdr_size = sizeof(*unicast_packet); |
989 | bool is4addr; | ||
988 | 990 | ||
989 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 991 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
990 | 992 | ||
993 | is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR; | ||
991 | /* the caller function should have already pulled 2 bytes */ | 994 | /* the caller function should have already pulled 2 bytes */ |
992 | if (unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR) | 995 | if (is4addr) |
993 | hdr_size = sizeof(struct batadv_unicast_4addr_packet); | 996 | hdr_size = sizeof(struct batadv_unicast_4addr_packet); |
994 | 997 | ||
995 | if (batadv_check_unicast_packet(skb, hdr_size) < 0) | 998 | if (batadv_check_unicast_packet(skb, hdr_size) < 0) |
@@ -1000,9 +1003,17 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1000 | 1003 | ||
1001 | /* packet for me */ | 1004 | /* packet for me */ |
1002 | if (batadv_is_my_mac(unicast_packet->dest)) { | 1005 | if (batadv_is_my_mac(unicast_packet->dest)) { |
1006 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, | ||
1007 | hdr_size)) | ||
1008 | goto rx_success; | ||
1009 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, | ||
1010 | hdr_size)) | ||
1011 | goto rx_success; | ||
1012 | |||
1003 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, | 1013 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1004 | NULL); | 1014 | NULL); |
1005 | 1015 | ||
1016 | rx_success: | ||
1006 | return NET_RX_SUCCESS; | 1017 | return NET_RX_SUCCESS; |
1007 | } | 1018 | } |
1008 | 1019 | ||
@@ -1038,8 +1049,17 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb, | |||
1038 | if (!new_skb) | 1049 | if (!new_skb) |
1039 | return NET_RX_SUCCESS; | 1050 | return NET_RX_SUCCESS; |
1040 | 1051 | ||
1052 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb, | ||
1053 | hdr_size)) | ||
1054 | goto rx_success; | ||
1055 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb, | ||
1056 | hdr_size)) | ||
1057 | goto rx_success; | ||
1058 | |||
1041 | batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, | 1059 | batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, |
1042 | sizeof(struct batadv_unicast_packet), NULL); | 1060 | sizeof(struct batadv_unicast_packet), NULL); |
1061 | |||
1062 | rx_success: | ||
1043 | return NET_RX_SUCCESS; | 1063 | return NET_RX_SUCCESS; |
1044 | } | 1064 | } |
1045 | 1065 | ||
@@ -1131,9 +1151,16 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, | |||
1131 | if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) | 1151 | if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) |
1132 | goto out; | 1152 | goto out; |
1133 | 1153 | ||
1154 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size)) | ||
1155 | goto rx_success; | ||
1156 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) | ||
1157 | goto rx_success; | ||
1158 | |||
1134 | /* broadcast for me */ | 1159 | /* broadcast for me */ |
1135 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, | 1160 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1136 | orig_node); | 1161 | orig_node); |
1162 | |||
1163 | rx_success: | ||
1137 | ret = NET_RX_SUCCESS; | 1164 | ret = NET_RX_SUCCESS; |
1138 | goto out; | 1165 | goto out; |
1139 | 1166 | ||
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 570a8bce0364..660d9bf7d219 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "main.h" | 20 | #include "main.h" |
21 | #include "distributed-arp-table.h" | ||
21 | #include "send.h" | 22 | #include "send.h" |
22 | #include "routing.h" | 23 | #include "routing.h" |
23 | #include "translation-table.h" | 24 | #include "translation-table.h" |
@@ -209,6 +210,9 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work) | |||
209 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) | 210 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) |
210 | goto out; | 211 | goto out; |
211 | 212 | ||
213 | if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet)) | ||
214 | goto out; | ||
215 | |||
212 | /* rebroadcast packet */ | 216 | /* rebroadcast packet */ |
213 | rcu_read_lock(); | 217 | rcu_read_lock(); |
214 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | 218 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 2f123a1b174b..9dc0ae1d4da3 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "main.h" | 20 | #include "main.h" |
21 | #include "soft-interface.h" | 21 | #include "soft-interface.h" |
22 | #include "hard-interface.h" | 22 | #include "hard-interface.h" |
23 | #include "distributed-arp-table.h" | ||
23 | #include "routing.h" | 24 | #include "routing.h" |
24 | #include "send.h" | 25 | #include "send.h" |
25 | #include "debugfs.h" | 26 | #include "debugfs.h" |
@@ -155,6 +156,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
155 | short vid __maybe_unused = -1; | 156 | short vid __maybe_unused = -1; |
156 | bool do_bcast = false; | 157 | bool do_bcast = false; |
157 | uint32_t seqno; | 158 | uint32_t seqno; |
159 | unsigned long brd_delay = 1; | ||
158 | 160 | ||
159 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 161 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
160 | goto dropped; | 162 | goto dropped; |
@@ -224,6 +226,13 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
224 | if (!primary_if) | 226 | if (!primary_if) |
225 | goto dropped; | 227 | goto dropped; |
226 | 228 | ||
229 | /* in case of ARP request, we do not immediately broadcasti the | ||
230 | * packet, instead we first wait for DAT to try to retrieve the | ||
231 | * correct ARP entry | ||
232 | */ | ||
233 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) | ||
234 | brd_delay = msecs_to_jiffies(ARP_REQ_DELAY); | ||
235 | |||
227 | if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) | 236 | if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) |
228 | goto dropped; | 237 | goto dropped; |
229 | 238 | ||
@@ -245,7 +254,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
245 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); | 254 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); |
246 | bcast_packet->seqno = htonl(seqno); | 255 | bcast_packet->seqno = htonl(seqno); |
247 | 256 | ||
248 | batadv_add_bcast_packet_to_list(bat_priv, skb, 1); | 257 | batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay); |
249 | 258 | ||
250 | /* a copy is stored in the bcast list, therefore removing | 259 | /* a copy is stored in the bcast list, therefore removing |
251 | * the original skb. | 260 | * the original skb. |
@@ -260,6 +269,11 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
260 | goto dropped; | 269 | goto dropped; |
261 | } | 270 | } |
262 | 271 | ||
272 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) | ||
273 | goto dropped; | ||
274 | |||
275 | batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb); | ||
276 | |||
263 | ret = batadv_unicast_send_skb(bat_priv, skb); | 277 | ret = batadv_unicast_send_skb(bat_priv, skb); |
264 | if (ret != 0) | 278 | if (ret != 0) |
265 | goto dropped_freed; | 279 | goto dropped_freed; |