19
19
20
20
#include <linux/if_ether.h>
21
21
#include <linux/if_arp.h>
22
+ #include <linux/if_vlan.h>
22
23
#include <net/arp.h>
23
24
24
25
#include "main.h"
@@ -205,15 +206,11 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
205
206
*/
206
207
static uint32_t batadv_hash_dat (const void * data , uint32_t size )
207
208
{
208
- const unsigned char * key = data ;
209
209
uint32_t hash = 0 ;
210
- size_t i ;
210
+ const struct batadv_dat_entry * dat = data ;
211
211
212
- for (i = 0 ; i < 4 ; i ++ ) {
213
- hash += key [i ];
214
- hash += (hash << 10 );
215
- hash ^= (hash >> 6 );
216
- }
212
+ hash = batadv_hash_bytes (hash , & dat -> ip , sizeof (dat -> ip ));
213
+ hash = batadv_hash_bytes (hash , & dat -> vid , sizeof (dat -> vid ));
217
214
218
215
hash += (hash << 3 );
219
216
hash ^= (hash >> 11 );
@@ -227,21 +224,26 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size)
227
224
* table
228
225
* @bat_priv: the bat priv with all the soft interface information
229
226
* @ip: search key
227
+ * @vid: VLAN identifier
230
228
*
231
229
* Returns the dat_entry if found, NULL otherwise.
232
230
*/
233
231
static struct batadv_dat_entry *
234
- batadv_dat_entry_hash_find (struct batadv_priv * bat_priv , __be32 ip )
232
+ batadv_dat_entry_hash_find (struct batadv_priv * bat_priv , __be32 ip ,
233
+ unsigned short vid )
235
234
{
236
235
struct hlist_head * head ;
237
- struct batadv_dat_entry * dat_entry , * dat_entry_tmp = NULL ;
236
+ struct batadv_dat_entry to_find , * dat_entry , * dat_entry_tmp = NULL ;
238
237
struct batadv_hashtable * hash = bat_priv -> dat .hash ;
239
238
uint32_t index ;
240
239
241
240
if (!hash )
242
241
return NULL ;
243
242
244
- index = batadv_hash_dat (& ip , hash -> size );
243
+ to_find .ip = ip ;
244
+ to_find .vid = vid ;
245
+
246
+ index = batadv_hash_dat (& to_find , hash -> size );
245
247
head = & hash -> table [index ];
246
248
247
249
rcu_read_lock ();
@@ -265,22 +267,24 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
265
267
* @bat_priv: the bat priv with all the soft interface information
266
268
* @ip: ipv4 to add/edit
267
269
* @mac_addr: mac address to assign to the given ipv4
270
+ * @vid: VLAN identifier
268
271
*/
269
272
static void batadv_dat_entry_add (struct batadv_priv * bat_priv , __be32 ip ,
270
- uint8_t * mac_addr )
273
+ uint8_t * mac_addr , unsigned short vid )
271
274
{
272
275
struct batadv_dat_entry * dat_entry ;
273
276
int hash_added ;
274
277
275
- dat_entry = batadv_dat_entry_hash_find (bat_priv , ip );
278
+ dat_entry = batadv_dat_entry_hash_find (bat_priv , ip , vid );
276
279
/* if this entry is already known, just update it */
277
280
if (dat_entry ) {
278
281
if (!batadv_compare_eth (dat_entry -> mac_addr , mac_addr ))
279
282
memcpy (dat_entry -> mac_addr , mac_addr , ETH_ALEN );
280
283
dat_entry -> last_update = jiffies ;
281
284
batadv_dbg (BATADV_DBG_DAT , bat_priv ,
282
- "Entry updated: %pI4 %pM\n" , & dat_entry -> ip ,
283
- dat_entry -> mac_addr );
285
+ "Entry updated: %pI4 %pM (vid: %d)\n" ,
286
+ & dat_entry -> ip , dat_entry -> mac_addr ,
287
+ BATADV_PRINT_VID (vid ));
284
288
goto out ;
285
289
}
286
290
@@ -289,12 +293,13 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
289
293
goto out ;
290
294
291
295
dat_entry -> ip = ip ;
296
+ dat_entry -> vid = vid ;
292
297
memcpy (dat_entry -> mac_addr , mac_addr , ETH_ALEN );
293
298
dat_entry -> last_update = jiffies ;
294
299
atomic_set (& dat_entry -> refcount , 2 );
295
300
296
301
hash_added = batadv_hash_add (bat_priv -> dat .hash , batadv_compare_dat ,
297
- batadv_hash_dat , & dat_entry -> ip ,
302
+ batadv_hash_dat , dat_entry ,
298
303
& dat_entry -> hash_entry );
299
304
300
305
if (unlikely (hash_added != 0 )) {
@@ -303,8 +308,8 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
303
308
goto out ;
304
309
}
305
310
306
- batadv_dbg (BATADV_DBG_DAT , bat_priv , "New entry added: %pI4 %pM\n" ,
307
- & dat_entry -> ip , dat_entry -> mac_addr );
311
+ batadv_dbg (BATADV_DBG_DAT , bat_priv , "New entry added: %pI4 %pM (vid: %d) \n" ,
312
+ & dat_entry -> ip , dat_entry -> mac_addr , BATADV_PRINT_VID ( vid ) );
308
313
309
314
out :
310
315
if (dat_entry )
@@ -756,8 +761,8 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
756
761
goto out ;
757
762
758
763
seq_printf (seq , "Distributed ARP Table (%s):\n" , net_dev -> name );
759
- seq_printf (seq , " %-7s %-13s %5s \n" , "IPv4" , "MAC " ,
760
- "last-seen" );
764
+ seq_printf (seq , " %-7s %-9s %4s %11s \n" , "IPv4" ,
765
+ "MAC" , "VID" , " last-seen" );
761
766
762
767
for (i = 0 ; i < hash -> size ; i ++ ) {
763
768
head = & hash -> table [i ];
@@ -770,8 +775,9 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
770
775
last_seen_msecs = last_seen_msecs % 60000 ;
771
776
last_seen_secs = last_seen_msecs / 1000 ;
772
777
773
- seq_printf (seq , " * %15pI4 %14pM %6i:%02i\n" ,
778
+ seq_printf (seq , " * %15pI4 %14pM %4i % 6i:%02i\n" ,
774
779
& dat_entry -> ip , dat_entry -> mac_addr ,
780
+ BATADV_PRINT_VID (dat_entry -> vid ),
775
781
last_seen_mins , last_seen_secs );
776
782
}
777
783
rcu_read_unlock ();
@@ -857,6 +863,31 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
857
863
return type ;
858
864
}
859
865
866
+ /**
867
+ * batadv_dat_get_vid - extract the VLAN identifier from skb if any
868
+ * @skb: the buffer containing the packet to extract the VID from
869
+ * @hdr_size: the size of the batman-adv header encapsulating the packet
870
+ *
871
+ * If the packet embedded in the skb is vlan tagged this function returns the
872
+ * VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned.
873
+ */
874
+ static unsigned short batadv_dat_get_vid (struct sk_buff * skb , int * hdr_size )
875
+ {
876
+ unsigned short vid ;
877
+
878
+ vid = batadv_get_vid (skb , * hdr_size );
879
+
880
+ /* ARP parsing functions jump forward of hdr_size + ETH_HLEN.
881
+ * If the header contained in the packet is a VLAN one (which is longer)
882
+ * hdr_size is updated so that the functions will still skip the
883
+ * correct amount of bytes.
884
+ */
885
+ if (vid & BATADV_VLAN_HAS_TAG )
886
+ * hdr_size += VLAN_HLEN ;
887
+
888
+ return vid ;
889
+ }
890
+
860
891
/**
861
892
* batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
862
893
* answer using DAT
@@ -876,26 +907,31 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
876
907
bool ret = false;
877
908
struct batadv_dat_entry * dat_entry = NULL ;
878
909
struct sk_buff * skb_new ;
910
+ int hdr_size = 0 ;
911
+ unsigned short vid ;
879
912
880
913
if (!atomic_read (& bat_priv -> distributed_arp_table ))
881
914
goto out ;
882
915
883
- type = batadv_arp_get_type (bat_priv , skb , 0 );
916
+ vid = batadv_dat_get_vid (skb , & hdr_size );
917
+
918
+ type = batadv_arp_get_type (bat_priv , skb , hdr_size );
884
919
/* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast
885
920
* message to the selected DHT candidates
886
921
*/
887
922
if (type != ARPOP_REQUEST )
888
923
goto out ;
889
924
890
- batadv_dbg_arp (bat_priv , skb , type , 0 , "Parsing outgoing ARP REQUEST" );
925
+ batadv_dbg_arp (bat_priv , skb , type , hdr_size ,
926
+ "Parsing outgoing ARP REQUEST" );
891
927
892
- ip_src = batadv_arp_ip_src (skb , 0 );
893
- hw_src = batadv_arp_hw_src (skb , 0 );
894
- ip_dst = batadv_arp_ip_dst (skb , 0 );
928
+ ip_src = batadv_arp_ip_src (skb , hdr_size );
929
+ hw_src = batadv_arp_hw_src (skb , hdr_size );
930
+ ip_dst = batadv_arp_ip_dst (skb , hdr_size );
895
931
896
- batadv_dat_entry_add (bat_priv , ip_src , hw_src );
932
+ batadv_dat_entry_add (bat_priv , ip_src , hw_src , vid );
897
933
898
- dat_entry = batadv_dat_entry_hash_find (bat_priv , ip_dst );
934
+ dat_entry = batadv_dat_entry_hash_find (bat_priv , ip_dst , vid );
899
935
if (dat_entry ) {
900
936
/* If the ARP request is destined for a local client the local
901
937
* client will answer itself. DAT would only generate a
@@ -917,11 +953,15 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
917
953
if (!skb_new )
918
954
goto out ;
919
955
956
+ if (vid & BATADV_VLAN_HAS_TAG )
957
+ skb_new = vlan_insert_tag (skb_new , htons (ETH_P_8021Q ),
958
+ vid & VLAN_VID_MASK );
959
+
920
960
skb_reset_mac_header (skb_new );
921
961
skb_new -> protocol = eth_type_trans (skb_new ,
922
962
bat_priv -> soft_iface );
923
963
bat_priv -> stats .rx_packets ++ ;
924
- bat_priv -> stats .rx_bytes += skb -> len + ETH_HLEN ;
964
+ bat_priv -> stats .rx_bytes += skb -> len + ETH_HLEN + hdr_size ;
925
965
bat_priv -> soft_iface -> last_rx = jiffies ;
926
966
927
967
netif_rx (skb_new );
@@ -956,11 +996,14 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
956
996
struct sk_buff * skb_new ;
957
997
struct batadv_dat_entry * dat_entry = NULL ;
958
998
bool ret = false;
999
+ unsigned short vid ;
959
1000
int err ;
960
1001
961
1002
if (!atomic_read (& bat_priv -> distributed_arp_table ))
962
1003
goto out ;
963
1004
1005
+ vid = batadv_dat_get_vid (skb , & hdr_size );
1006
+
964
1007
type = batadv_arp_get_type (bat_priv , skb , hdr_size );
965
1008
if (type != ARPOP_REQUEST )
966
1009
goto out ;
@@ -972,9 +1015,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
972
1015
batadv_dbg_arp (bat_priv , skb , type , hdr_size ,
973
1016
"Parsing incoming ARP REQUEST" );
974
1017
975
- batadv_dat_entry_add (bat_priv , ip_src , hw_src );
1018
+ batadv_dat_entry_add (bat_priv , ip_src , hw_src , vid );
976
1019
977
- dat_entry = batadv_dat_entry_hash_find (bat_priv , ip_dst );
1020
+ dat_entry = batadv_dat_entry_hash_find (bat_priv , ip_dst , vid );
978
1021
if (!dat_entry )
979
1022
goto out ;
980
1023
@@ -985,17 +1028,20 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
985
1028
if (!skb_new )
986
1029
goto out ;
987
1030
1031
+ if (vid & BATADV_VLAN_HAS_TAG )
1032
+ skb_new = vlan_insert_tag (skb_new , htons (ETH_P_8021Q ),
1033
+ vid & VLAN_VID_MASK );
1034
+
988
1035
/* To preserve backwards compatibility, the node has choose the outgoing
989
1036
* format based on the incoming request packet type. The assumption is
990
1037
* that a node not using the 4addr packet format doesn't support it.
991
1038
*/
992
1039
if (hdr_size == sizeof (struct batadv_unicast_4addr_packet ))
993
1040
err = batadv_send_skb_unicast_4addr (bat_priv , skb_new ,
994
1041
BATADV_P_DAT_CACHE_REPLY ,
995
- BATADV_NO_FLAGS );
1042
+ vid );
996
1043
else
997
- err = batadv_send_skb_unicast (bat_priv , skb_new ,
998
- BATADV_NO_FLAGS );
1044
+ err = batadv_send_skb_unicast (bat_priv , skb_new , vid );
999
1045
1000
1046
if (!err ) {
1001
1047
batadv_inc_counter (bat_priv , BATADV_CNT_DAT_CACHED_REPLY_TX );
@@ -1020,23 +1066,28 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
1020
1066
uint16_t type ;
1021
1067
__be32 ip_src , ip_dst ;
1022
1068
uint8_t * hw_src , * hw_dst ;
1069
+ int hdr_size = 0 ;
1070
+ unsigned short vid ;
1023
1071
1024
1072
if (!atomic_read (& bat_priv -> distributed_arp_table ))
1025
1073
return ;
1026
1074
1027
- type = batadv_arp_get_type (bat_priv , skb , 0 );
1075
+ vid = batadv_dat_get_vid (skb , & hdr_size );
1076
+
1077
+ type = batadv_arp_get_type (bat_priv , skb , hdr_size );
1028
1078
if (type != ARPOP_REPLY )
1029
1079
return ;
1030
1080
1031
- batadv_dbg_arp (bat_priv , skb , type , 0 , "Parsing outgoing ARP REPLY" );
1081
+ batadv_dbg_arp (bat_priv , skb , type , hdr_size ,
1082
+ "Parsing outgoing ARP REPLY" );
1032
1083
1033
- hw_src = batadv_arp_hw_src (skb , 0 );
1034
- ip_src = batadv_arp_ip_src (skb , 0 );
1035
- hw_dst = batadv_arp_hw_dst (skb , 0 );
1036
- ip_dst = batadv_arp_ip_dst (skb , 0 );
1084
+ hw_src = batadv_arp_hw_src (skb , hdr_size );
1085
+ ip_src = batadv_arp_ip_src (skb , hdr_size );
1086
+ hw_dst = batadv_arp_hw_dst (skb , hdr_size );
1087
+ ip_dst = batadv_arp_ip_dst (skb , hdr_size );
1037
1088
1038
- batadv_dat_entry_add (bat_priv , ip_src , hw_src );
1039
- batadv_dat_entry_add (bat_priv , ip_dst , hw_dst );
1089
+ batadv_dat_entry_add (bat_priv , ip_src , hw_src , vid );
1090
+ batadv_dat_entry_add (bat_priv , ip_dst , hw_dst , vid );
1040
1091
1041
1092
/* Send the ARP reply to the candidates for both the IP addresses that
1042
1093
* the node obtained from the ARP reply
@@ -1058,10 +1109,13 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
1058
1109
__be32 ip_src , ip_dst ;
1059
1110
uint8_t * hw_src , * hw_dst ;
1060
1111
bool ret = false;
1112
+ unsigned short vid ;
1061
1113
1062
1114
if (!atomic_read (& bat_priv -> distributed_arp_table ))
1063
1115
goto out ;
1064
1116
1117
+ vid = batadv_dat_get_vid (skb , & hdr_size );
1118
+
1065
1119
type = batadv_arp_get_type (bat_priv , skb , hdr_size );
1066
1120
if (type != ARPOP_REPLY )
1067
1121
goto out ;
@@ -1077,13 +1131,13 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
1077
1131
/* Update our internal cache with both the IP addresses the node got
1078
1132
* within the ARP reply
1079
1133
*/
1080
- batadv_dat_entry_add (bat_priv , ip_src , hw_src );
1081
- batadv_dat_entry_add (bat_priv , ip_dst , hw_dst );
1134
+ batadv_dat_entry_add (bat_priv , ip_src , hw_src , vid );
1135
+ batadv_dat_entry_add (bat_priv , ip_dst , hw_dst , vid );
1082
1136
1083
1137
/* if this REPLY is directed to a client of mine, let's deliver the
1084
1138
* packet to the interface
1085
1139
*/
1086
- ret = !batadv_is_my_client (bat_priv , hw_dst , BATADV_NO_FLAGS );
1140
+ ret = !batadv_is_my_client (bat_priv , hw_dst , vid );
1087
1141
out :
1088
1142
if (ret )
1089
1143
kfree_skb (skb );
@@ -1106,7 +1160,8 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
1106
1160
__be32 ip_dst ;
1107
1161
struct batadv_dat_entry * dat_entry = NULL ;
1108
1162
bool ret = false;
1109
- const size_t bcast_len = sizeof (struct batadv_bcast_packet );
1163
+ int hdr_size = sizeof (struct batadv_bcast_packet );
1164
+ unsigned short vid ;
1110
1165
1111
1166
if (!atomic_read (& bat_priv -> distributed_arp_table ))
1112
1167
goto out ;
@@ -1117,12 +1172,14 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
1117
1172
if (forw_packet -> num_packets )
1118
1173
goto out ;
1119
1174
1120
- type = batadv_arp_get_type (bat_priv , forw_packet -> skb , bcast_len );
1175
+ vid = batadv_dat_get_vid (forw_packet -> skb , & hdr_size );
1176
+
1177
+ type = batadv_arp_get_type (bat_priv , forw_packet -> skb , hdr_size );
1121
1178
if (type != ARPOP_REQUEST )
1122
1179
goto out ;
1123
1180
1124
- ip_dst = batadv_arp_ip_dst (forw_packet -> skb , bcast_len );
1125
- dat_entry = batadv_dat_entry_hash_find (bat_priv , ip_dst );
1181
+ ip_dst = batadv_arp_ip_dst (forw_packet -> skb , hdr_size );
1182
+ dat_entry = batadv_dat_entry_hash_find (bat_priv , ip_dst , vid );
1126
1183
/* check if the node already got this entry */
1127
1184
if (!dat_entry ) {
1128
1185
batadv_dbg (BATADV_DBG_DAT , bat_priv ,
0 commit comments