diff options
Diffstat (limited to 'net/batman-adv')
26 files changed, 2329 insertions, 469 deletions
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index 53f5244e28f8..250e0b58109c 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig | |||
@@ -25,6 +25,16 @@ config BATMAN_ADV_BLA | |||
25 | more than one mesh node in the same LAN, you can safely remove | 25 | more than one mesh node in the same LAN, you can safely remove |
26 | this feature and save some space. | 26 | this feature and save some space. |
27 | 27 | ||
28 | config BATMAN_ADV_DAT | ||
29 | bool "Distributed ARP Table" | ||
30 | depends on BATMAN_ADV && INET | ||
31 | default n | ||
32 | help | ||
33 | This option enables DAT (Distributed ARP Table), a DHT based | ||
34 | mechanism that increases ARP reliability on sparse wireless | ||
35 | mesh networks. If you think that your network does not need | ||
36 | this option you can safely remove it and save some space. | ||
37 | |||
28 | config BATMAN_ADV_DEBUG | 38 | config BATMAN_ADV_DEBUG |
29 | bool "B.A.T.M.A.N. debugging" | 39 | bool "B.A.T.M.A.N. debugging" |
30 | depends on BATMAN_ADV | 40 | depends on BATMAN_ADV |
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index 8676d2b1d574..e45e3b4e32e3 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile | |||
@@ -23,6 +23,7 @@ batman-adv-y += bat_iv_ogm.o | |||
23 | batman-adv-y += bitarray.o | 23 | batman-adv-y += bitarray.o |
24 | batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o | 24 | batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o |
25 | batman-adv-y += debugfs.o | 25 | batman-adv-y += debugfs.o |
26 | batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o | ||
26 | batman-adv-y += gateway_client.o | 27 | batman-adv-y += gateway_client.o |
27 | batman-adv-y += gateway_common.o | 28 | batman-adv-y += gateway_common.o |
28 | batman-adv-y += hard-interface.o | 29 | batman-adv-y += hard-interface.o |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index b02b75dae3a8..9f3925a85aab 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -57,20 +57,22 @@ out: | |||
57 | static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) | 57 | static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) |
58 | { | 58 | { |
59 | struct batadv_ogm_packet *batadv_ogm_packet; | 59 | struct batadv_ogm_packet *batadv_ogm_packet; |
60 | unsigned char *ogm_buff; | ||
60 | uint32_t random_seqno; | 61 | uint32_t random_seqno; |
61 | int res = -ENOMEM; | 62 | int res = -ENOMEM; |
62 | 63 | ||
63 | /* randomize initial seqno to avoid collision */ | 64 | /* randomize initial seqno to avoid collision */ |
64 | get_random_bytes(&random_seqno, sizeof(random_seqno)); | 65 | get_random_bytes(&random_seqno, sizeof(random_seqno)); |
65 | atomic_set(&hard_iface->seqno, random_seqno); | 66 | atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno); |
66 | 67 | ||
67 | hard_iface->packet_len = BATADV_OGM_HLEN; | 68 | hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN; |
68 | hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC); | 69 | ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC); |
69 | 70 | if (!ogm_buff) | |
70 | if (!hard_iface->packet_buff) | ||
71 | goto out; | 71 | goto out; |
72 | 72 | ||
73 | batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff; | 73 | hard_iface->bat_iv.ogm_buff = ogm_buff; |
74 | |||
75 | batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; | ||
74 | batadv_ogm_packet->header.packet_type = BATADV_IV_OGM; | 76 | batadv_ogm_packet->header.packet_type = BATADV_IV_OGM; |
75 | batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; | 77 | batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; |
76 | batadv_ogm_packet->header.ttl = 2; | 78 | batadv_ogm_packet->header.ttl = 2; |
@@ -87,15 +89,16 @@ out: | |||
87 | 89 | ||
88 | static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) | 90 | static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) |
89 | { | 91 | { |
90 | kfree(hard_iface->packet_buff); | 92 | kfree(hard_iface->bat_iv.ogm_buff); |
91 | hard_iface->packet_buff = NULL; | 93 | hard_iface->bat_iv.ogm_buff = NULL; |
92 | } | 94 | } |
93 | 95 | ||
94 | static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) | 96 | static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) |
95 | { | 97 | { |
96 | struct batadv_ogm_packet *batadv_ogm_packet; | 98 | struct batadv_ogm_packet *batadv_ogm_packet; |
99 | unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; | ||
97 | 100 | ||
98 | batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff; | 101 | batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; |
99 | memcpy(batadv_ogm_packet->orig, | 102 | memcpy(batadv_ogm_packet->orig, |
100 | hard_iface->net_dev->dev_addr, ETH_ALEN); | 103 | hard_iface->net_dev->dev_addr, ETH_ALEN); |
101 | memcpy(batadv_ogm_packet->prev_sender, | 104 | memcpy(batadv_ogm_packet->prev_sender, |
@@ -106,8 +109,9 @@ static void | |||
106 | batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) | 109 | batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) |
107 | { | 110 | { |
108 | struct batadv_ogm_packet *batadv_ogm_packet; | 111 | struct batadv_ogm_packet *batadv_ogm_packet; |
112 | unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; | ||
109 | 113 | ||
110 | batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff; | 114 | batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; |
111 | batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP; | 115 | batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP; |
112 | batadv_ogm_packet->header.ttl = BATADV_TTL; | 116 | batadv_ogm_packet->header.ttl = BATADV_TTL; |
113 | } | 117 | } |
@@ -407,9 +411,11 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, | |||
407 | 411 | ||
408 | if ((atomic_read(&bat_priv->aggregated_ogms)) && | 412 | if ((atomic_read(&bat_priv->aggregated_ogms)) && |
409 | (packet_len < BATADV_MAX_AGGREGATION_BYTES)) | 413 | (packet_len < BATADV_MAX_AGGREGATION_BYTES)) |
410 | skb_size = BATADV_MAX_AGGREGATION_BYTES + ETH_HLEN; | 414 | skb_size = BATADV_MAX_AGGREGATION_BYTES; |
411 | else | 415 | else |
412 | skb_size = packet_len + ETH_HLEN; | 416 | skb_size = packet_len; |
417 | |||
418 | skb_size += ETH_HLEN + NET_IP_ALIGN; | ||
413 | 419 | ||
414 | forw_packet_aggr->skb = dev_alloc_skb(skb_size); | 420 | forw_packet_aggr->skb = dev_alloc_skb(skb_size); |
415 | if (!forw_packet_aggr->skb) { | 421 | if (!forw_packet_aggr->skb) { |
@@ -418,7 +424,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, | |||
418 | kfree(forw_packet_aggr); | 424 | kfree(forw_packet_aggr); |
419 | goto out; | 425 | goto out; |
420 | } | 426 | } |
421 | skb_reserve(forw_packet_aggr->skb, ETH_HLEN); | 427 | skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN); |
422 | 428 | ||
423 | INIT_HLIST_NODE(&forw_packet_aggr->list); | 429 | INIT_HLIST_NODE(&forw_packet_aggr->list); |
424 | 430 | ||
@@ -590,8 +596,10 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, | |||
590 | static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | 596 | static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) |
591 | { | 597 | { |
592 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 598 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
599 | unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff; | ||
593 | struct batadv_ogm_packet *batadv_ogm_packet; | 600 | struct batadv_ogm_packet *batadv_ogm_packet; |
594 | struct batadv_hard_iface *primary_if; | 601 | struct batadv_hard_iface *primary_if; |
602 | int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; | ||
595 | int vis_server, tt_num_changes = 0; | 603 | int vis_server, tt_num_changes = 0; |
596 | uint32_t seqno; | 604 | uint32_t seqno; |
597 | uint8_t bandwidth; | 605 | uint8_t bandwidth; |
@@ -600,17 +608,16 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
600 | primary_if = batadv_primary_if_get_selected(bat_priv); | 608 | primary_if = batadv_primary_if_get_selected(bat_priv); |
601 | 609 | ||
602 | if (hard_iface == primary_if) | 610 | if (hard_iface == primary_if) |
603 | tt_num_changes = batadv_tt_append_diff(bat_priv, | 611 | tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff, |
604 | &hard_iface->packet_buff, | 612 | ogm_buff_len, |
605 | &hard_iface->packet_len, | ||
606 | BATADV_OGM_HLEN); | 613 | BATADV_OGM_HLEN); |
607 | 614 | ||
608 | batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff; | 615 | batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff); |
609 | 616 | ||
610 | /* change sequence number to network order */ | 617 | /* change sequence number to network order */ |
611 | seqno = (uint32_t)atomic_read(&hard_iface->seqno); | 618 | seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno); |
612 | batadv_ogm_packet->seqno = htonl(seqno); | 619 | batadv_ogm_packet->seqno = htonl(seqno); |
613 | atomic_inc(&hard_iface->seqno); | 620 | atomic_inc(&hard_iface->bat_iv.ogm_seqno); |
614 | 621 | ||
615 | batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn); | 622 | batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn); |
616 | batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc); | 623 | batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc); |
@@ -631,8 +638,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
631 | } | 638 | } |
632 | 639 | ||
633 | batadv_slide_own_bcast_window(hard_iface); | 640 | batadv_slide_own_bcast_window(hard_iface); |
634 | batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff, | 641 | batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, |
635 | hard_iface->packet_len, hard_iface, 1, | 642 | hard_iface->bat_iv.ogm_buff_len, hard_iface, 1, |
636 | batadv_iv_ogm_emit_send_time(bat_priv)); | 643 | batadv_iv_ogm_emit_send_time(bat_priv)); |
637 | 644 | ||
638 | if (primary_if) | 645 | if (primary_if) |
@@ -1015,7 +1022,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
1015 | return; | 1022 | return; |
1016 | 1023 | ||
1017 | /* could be changed by schedule_own_packet() */ | 1024 | /* could be changed by schedule_own_packet() */ |
1018 | if_incoming_seqno = atomic_read(&if_incoming->seqno); | 1025 | if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno); |
1019 | 1026 | ||
1020 | if (batadv_ogm_packet->flags & BATADV_DIRECTLINK) | 1027 | if (batadv_ogm_packet->flags & BATADV_DIRECTLINK) |
1021 | has_directlink_flag = 1; | 1028 | has_directlink_flag = 1; |
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index aea174cdbfbd..5453b17d8df2 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c | |||
@@ -79,20 +79,17 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, | |||
79 | * or the old packet got delayed somewhere in the network. The | 79 | * or the old packet got delayed somewhere in the network. The |
80 | * packet should be dropped without calling this function if the | 80 | * packet should be dropped without calling this function if the |
81 | * seqno window is protected. | 81 | * seqno window is protected. |
82 | * | ||
83 | * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE | ||
84 | * or | ||
85 | * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE | ||
82 | */ | 86 | */ |
83 | if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE || | 87 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
84 | seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) { | 88 | "Other host probably restarted!\n"); |
85 | 89 | ||
86 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 90 | bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
87 | "Other host probably restarted!\n"); | 91 | if (set_mark) |
88 | 92 | batadv_set_bit(seq_bits, 0); | |
89 | bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | ||
90 | if (set_mark) | ||
91 | batadv_set_bit(seq_bits, 0); | ||
92 | |||
93 | return 1; | ||
94 | } | ||
95 | 93 | ||
96 | /* never reached */ | 94 | return 1; |
97 | return 0; | ||
98 | } | 95 | } |
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index fd8d5afec0dd..bda8b1710806 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
@@ -40,15 +40,11 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv, | |||
40 | /* return the index of the claim */ | 40 | /* return the index of the claim */ |
41 | static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) | 41 | static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) |
42 | { | 42 | { |
43 | const unsigned char *key = data; | 43 | struct batadv_claim *claim = (struct batadv_claim *)data; |
44 | uint32_t hash = 0; | 44 | uint32_t hash = 0; |
45 | size_t i; | ||
46 | 45 | ||
47 | for (i = 0; i < ETH_ALEN + sizeof(short); i++) { | 46 | hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr)); |
48 | hash += key[i]; | 47 | hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid)); |
49 | hash += (hash << 10); | ||
50 | hash ^= (hash >> 6); | ||
51 | } | ||
52 | 48 | ||
53 | hash += (hash << 3); | 49 | hash += (hash << 3); |
54 | hash ^= (hash >> 11); | 50 | hash ^= (hash >> 11); |
@@ -61,15 +57,11 @@ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) | |||
61 | static inline uint32_t batadv_choose_backbone_gw(const void *data, | 57 | static inline uint32_t batadv_choose_backbone_gw(const void *data, |
62 | uint32_t size) | 58 | uint32_t size) |
63 | { | 59 | { |
64 | const unsigned char *key = data; | 60 | struct batadv_claim *claim = (struct batadv_claim *)data; |
65 | uint32_t hash = 0; | 61 | uint32_t hash = 0; |
66 | size_t i; | ||
67 | 62 | ||
68 | for (i = 0; i < ETH_ALEN + sizeof(short); i++) { | 63 | hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr)); |
69 | hash += key[i]; | 64 | hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid)); |
70 | hash += (hash << 10); | ||
71 | hash ^= (hash >> 6); | ||
72 | } | ||
73 | 65 | ||
74 | hash += (hash << 3); | 66 | hash += (hash << 3); |
75 | hash ^= (hash >> 11); | 67 | hash ^= (hash >> 11); |
@@ -362,7 +354,7 @@ out: | |||
362 | */ | 354 | */ |
363 | static struct batadv_backbone_gw * | 355 | static struct batadv_backbone_gw * |
364 | batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | 356 | batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, |
365 | short vid) | 357 | short vid, bool own_backbone) |
366 | { | 358 | { |
367 | struct batadv_backbone_gw *entry; | 359 | struct batadv_backbone_gw *entry; |
368 | struct batadv_orig_node *orig_node; | 360 | struct batadv_orig_node *orig_node; |
@@ -386,6 +378,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | |||
386 | entry->crc = BATADV_BLA_CRC_INIT; | 378 | entry->crc = BATADV_BLA_CRC_INIT; |
387 | entry->bat_priv = bat_priv; | 379 | entry->bat_priv = bat_priv; |
388 | atomic_set(&entry->request_sent, 0); | 380 | atomic_set(&entry->request_sent, 0); |
381 | atomic_set(&entry->wait_periods, 0); | ||
389 | memcpy(entry->orig, orig, ETH_ALEN); | 382 | memcpy(entry->orig, orig, ETH_ALEN); |
390 | 383 | ||
391 | /* one for the hash, one for returning */ | 384 | /* one for the hash, one for returning */ |
@@ -409,6 +402,16 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | |||
409 | "became a backbone gateway"); | 402 | "became a backbone gateway"); |
410 | batadv_orig_node_free_ref(orig_node); | 403 | batadv_orig_node_free_ref(orig_node); |
411 | } | 404 | } |
405 | |||
406 | if (own_backbone) { | ||
407 | batadv_bla_send_announce(bat_priv, entry); | ||
408 | |||
409 | /* this will be decreased in the worker thread */ | ||
410 | atomic_inc(&entry->request_sent); | ||
411 | atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS); | ||
412 | atomic_inc(&bat_priv->bla.num_requests); | ||
413 | } | ||
414 | |||
412 | return entry; | 415 | return entry; |
413 | } | 416 | } |
414 | 417 | ||
@@ -424,7 +427,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv, | |||
424 | 427 | ||
425 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, | 428 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, |
426 | primary_if->net_dev->dev_addr, | 429 | primary_if->net_dev->dev_addr, |
427 | vid); | 430 | vid, true); |
428 | if (unlikely(!backbone_gw)) | 431 | if (unlikely(!backbone_gw)) |
429 | return; | 432 | return; |
430 | 433 | ||
@@ -632,7 +635,8 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, | |||
632 | if (memcmp(an_addr, batadv_announce_mac, 4) != 0) | 635 | if (memcmp(an_addr, batadv_announce_mac, 4) != 0) |
633 | return 0; | 636 | return 0; |
634 | 637 | ||
635 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid); | 638 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid, |
639 | false); | ||
636 | 640 | ||
637 | if (unlikely(!backbone_gw)) | 641 | if (unlikely(!backbone_gw)) |
638 | return 1; | 642 | return 1; |
@@ -730,7 +734,8 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv, | |||
730 | 734 | ||
731 | /* register the gateway if not yet available, and add the claim. */ | 735 | /* register the gateway if not yet available, and add the claim. */ |
732 | 736 | ||
733 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid); | 737 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid, |
738 | false); | ||
734 | 739 | ||
735 | if (unlikely(!backbone_gw)) | 740 | if (unlikely(!backbone_gw)) |
736 | return 1; | 741 | return 1; |
@@ -1140,6 +1145,24 @@ static void batadv_bla_periodic_work(struct work_struct *work) | |||
1140 | backbone_gw->lasttime = jiffies; | 1145 | backbone_gw->lasttime = jiffies; |
1141 | 1146 | ||
1142 | batadv_bla_send_announce(bat_priv, backbone_gw); | 1147 | batadv_bla_send_announce(bat_priv, backbone_gw); |
1148 | |||
1149 | /* request_sent is only set after creation to avoid | ||
1150 | * problems when we are not yet known as backbone gw | ||
1151 | * in the backbone. | ||
1152 | * | ||
1153 | * We can reset this now after we waited some periods | ||
1154 | * to give bridge forward delays and bla group forming | ||
1155 | * some grace time. | ||
1156 | */ | ||
1157 | |||
1158 | if (atomic_read(&backbone_gw->request_sent) == 0) | ||
1159 | continue; | ||
1160 | |||
1161 | if (!atomic_dec_and_test(&backbone_gw->wait_periods)) | ||
1162 | continue; | ||
1163 | |||
1164 | atomic_dec(&backbone_gw->bat_priv->bla.num_requests); | ||
1165 | atomic_set(&backbone_gw->request_sent, 0); | ||
1143 | } | 1166 | } |
1144 | rcu_read_unlock(); | 1167 | rcu_read_unlock(); |
1145 | } | 1168 | } |
@@ -1585,23 +1608,11 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1585 | struct hlist_head *head; | 1608 | struct hlist_head *head; |
1586 | uint32_t i; | 1609 | uint32_t i; |
1587 | bool is_own; | 1610 | bool is_own; |
1588 | int ret = 0; | ||
1589 | uint8_t *primary_addr; | 1611 | uint8_t *primary_addr; |
1590 | 1612 | ||
1591 | primary_if = batadv_primary_if_get_selected(bat_priv); | 1613 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
1592 | if (!primary_if) { | 1614 | if (!primary_if) |
1593 | ret = seq_printf(seq, | ||
1594 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
1595 | net_dev->name); | ||
1596 | goto out; | ||
1597 | } | ||
1598 | |||
1599 | if (primary_if->if_status != BATADV_IF_ACTIVE) { | ||
1600 | ret = seq_printf(seq, | ||
1601 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
1602 | net_dev->name); | ||
1603 | goto out; | 1615 | goto out; |
1604 | } | ||
1605 | 1616 | ||
1606 | primary_addr = primary_if->net_dev->dev_addr; | 1617 | primary_addr = primary_if->net_dev->dev_addr; |
1607 | seq_printf(seq, | 1618 | seq_printf(seq, |
@@ -1628,7 +1639,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1628 | out: | 1639 | out: |
1629 | if (primary_if) | 1640 | if (primary_if) |
1630 | batadv_hardif_free_ref(primary_if); | 1641 | batadv_hardif_free_ref(primary_if); |
1631 | return ret; | 1642 | return 0; |
1632 | } | 1643 | } |
1633 | 1644 | ||
1634 | int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) | 1645 | int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) |
@@ -1643,23 +1654,11 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1643 | int secs, msecs; | 1654 | int secs, msecs; |
1644 | uint32_t i; | 1655 | uint32_t i; |
1645 | bool is_own; | 1656 | bool is_own; |
1646 | int ret = 0; | ||
1647 | uint8_t *primary_addr; | 1657 | uint8_t *primary_addr; |
1648 | 1658 | ||
1649 | primary_if = batadv_primary_if_get_selected(bat_priv); | 1659 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
1650 | if (!primary_if) { | 1660 | if (!primary_if) |
1651 | ret = seq_printf(seq, | ||
1652 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
1653 | net_dev->name); | ||
1654 | goto out; | ||
1655 | } | ||
1656 | |||
1657 | if (primary_if->if_status != BATADV_IF_ACTIVE) { | ||
1658 | ret = seq_printf(seq, | ||
1659 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
1660 | net_dev->name); | ||
1661 | goto out; | 1661 | goto out; |
1662 | } | ||
1663 | 1662 | ||
1664 | primary_addr = primary_if->net_dev->dev_addr; | 1663 | primary_addr = primary_if->net_dev->dev_addr; |
1665 | seq_printf(seq, | 1664 | seq_printf(seq, |
@@ -1693,5 +1692,5 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1693 | out: | 1692 | out: |
1694 | if (primary_if) | 1693 | if (primary_if) |
1695 | batadv_hardif_free_ref(primary_if); | 1694 | batadv_hardif_free_ref(primary_if); |
1696 | return ret; | 1695 | return 0; |
1697 | } | 1696 | } |
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 391d4fb2026f..3f679cb2d0e2 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "vis.h" | 31 | #include "vis.h" |
32 | #include "icmp_socket.h" | 32 | #include "icmp_socket.h" |
33 | #include "bridge_loop_avoidance.h" | 33 | #include "bridge_loop_avoidance.h" |
34 | #include "distributed-arp-table.h" | ||
34 | 35 | ||
35 | static struct dentry *batadv_debugfs; | 36 | static struct dentry *batadv_debugfs; |
36 | 37 | ||
@@ -99,15 +100,17 @@ int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) | |||
99 | 100 | ||
100 | static int batadv_log_open(struct inode *inode, struct file *file) | 101 | static int batadv_log_open(struct inode *inode, struct file *file) |
101 | { | 102 | { |
103 | if (!try_module_get(THIS_MODULE)) | ||
104 | return -EBUSY; | ||
105 | |||
102 | nonseekable_open(inode, file); | 106 | nonseekable_open(inode, file); |
103 | file->private_data = inode->i_private; | 107 | file->private_data = inode->i_private; |
104 | batadv_inc_module_count(); | ||
105 | return 0; | 108 | return 0; |
106 | } | 109 | } |
107 | 110 | ||
108 | static int batadv_log_release(struct inode *inode, struct file *file) | 111 | static int batadv_log_release(struct inode *inode, struct file *file) |
109 | { | 112 | { |
110 | batadv_dec_module_count(); | 113 | module_put(THIS_MODULE); |
111 | return 0; | 114 | return 0; |
112 | } | 115 | } |
113 | 116 | ||
@@ -278,6 +281,19 @@ static int batadv_bla_backbone_table_open(struct inode *inode, | |||
278 | 281 | ||
279 | #endif | 282 | #endif |
280 | 283 | ||
284 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
285 | /** | ||
286 | * batadv_dat_cache_open - Prepare file handler for reads from dat_chache | ||
287 | * @inode: inode which was opened | ||
288 | * @file: file handle to be initialized | ||
289 | */ | ||
290 | static int batadv_dat_cache_open(struct inode *inode, struct file *file) | ||
291 | { | ||
292 | struct net_device *net_dev = (struct net_device *)inode->i_private; | ||
293 | return single_open(file, batadv_dat_cache_seq_print_text, net_dev); | ||
294 | } | ||
295 | #endif | ||
296 | |||
281 | static int batadv_transtable_local_open(struct inode *inode, struct file *file) | 297 | static int batadv_transtable_local_open(struct inode *inode, struct file *file) |
282 | { | 298 | { |
283 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 299 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
@@ -317,6 +333,9 @@ static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open); | |||
317 | static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO, | 333 | static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO, |
318 | batadv_bla_backbone_table_open); | 334 | batadv_bla_backbone_table_open); |
319 | #endif | 335 | #endif |
336 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
337 | static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open); | ||
338 | #endif | ||
320 | static BATADV_DEBUGINFO(transtable_local, S_IRUGO, | 339 | static BATADV_DEBUGINFO(transtable_local, S_IRUGO, |
321 | batadv_transtable_local_open); | 340 | batadv_transtable_local_open); |
322 | static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open); | 341 | static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open); |
@@ -329,6 +348,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { | |||
329 | &batadv_debuginfo_bla_claim_table, | 348 | &batadv_debuginfo_bla_claim_table, |
330 | &batadv_debuginfo_bla_backbone_table, | 349 | &batadv_debuginfo_bla_backbone_table, |
331 | #endif | 350 | #endif |
351 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
352 | &batadv_debuginfo_dat_cache, | ||
353 | #endif | ||
332 | &batadv_debuginfo_transtable_local, | 354 | &batadv_debuginfo_transtable_local, |
333 | &batadv_debuginfo_vis_data, | 355 | &batadv_debuginfo_vis_data, |
334 | NULL, | 356 | NULL, |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c new file mode 100644 index 000000000000..8e1d89d2b1c1 --- /dev/null +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -0,0 +1,1066 @@ | |||
1 | /* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors: | ||
2 | * | ||
3 | * Antonio Quartulli | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of version 2 of the GNU General Public | ||
7 | * License as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | * 02110-1301, USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/if_ether.h> | ||
21 | #include <linux/if_arp.h> | ||
22 | #include <net/arp.h> | ||
23 | |||
24 | #include "main.h" | ||
25 | #include "hash.h" | ||
26 | #include "distributed-arp-table.h" | ||
27 | #include "hard-interface.h" | ||
28 | #include "originator.h" | ||
29 | #include "send.h" | ||
30 | #include "types.h" | ||
31 | #include "translation-table.h" | ||
32 | #include "unicast.h" | ||
33 | |||
34 | static void batadv_dat_purge(struct work_struct *work); | ||
35 | |||
36 | /** | ||
37 | * batadv_dat_start_timer - initialise the DAT periodic worker | ||
38 | * @bat_priv: the bat priv with all the soft interface information | ||
39 | */ | ||
40 | static void batadv_dat_start_timer(struct batadv_priv *bat_priv) | ||
41 | { | ||
42 | INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge); | ||
43 | queue_delayed_work(batadv_event_workqueue, &bat_priv->dat.work, | ||
44 | msecs_to_jiffies(10000)); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * batadv_dat_entry_free_ref - decrements the dat_entry refcounter and possibly | ||
49 | * free it | ||
50 | * @dat_entry: the oentry to free | ||
51 | */ | ||
52 | static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry) | ||
53 | { | ||
54 | if (atomic_dec_and_test(&dat_entry->refcount)) | ||
55 | kfree_rcu(dat_entry, rcu); | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * batadv_dat_to_purge - checks whether a dat_entry has to be purged or not | ||
60 | * @dat_entry: the entry to check | ||
61 | * | ||
62 | * Returns true if the entry has to be purged now, false otherwise | ||
63 | */ | ||
64 | static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry) | ||
65 | { | ||
66 | return batadv_has_timed_out(dat_entry->last_update, | ||
67 | BATADV_DAT_ENTRY_TIMEOUT); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * __batadv_dat_purge - delete entries from the DAT local storage | ||
72 | * @bat_priv: the bat priv with all the soft interface information | ||
73 | * @to_purge: function in charge to decide whether an entry has to be purged or | ||
74 | * not. This function takes the dat_entry as argument and has to | ||
75 | * returns a boolean value: true is the entry has to be deleted, | ||
76 | * false otherwise | ||
77 | * | ||
78 | * Loops over each entry in the DAT local storage and delete it if and only if | ||
79 | * the to_purge function passed as argument returns true | ||
80 | */ | ||
81 | static void __batadv_dat_purge(struct batadv_priv *bat_priv, | ||
82 | bool (*to_purge)(struct batadv_dat_entry *)) | ||
83 | { | ||
84 | spinlock_t *list_lock; /* protects write access to the hash lists */ | ||
85 | struct batadv_dat_entry *dat_entry; | ||
86 | struct hlist_node *node, *node_tmp; | ||
87 | struct hlist_head *head; | ||
88 | uint32_t i; | ||
89 | |||
90 | if (!bat_priv->dat.hash) | ||
91 | return; | ||
92 | |||
93 | for (i = 0; i < bat_priv->dat.hash->size; i++) { | ||
94 | head = &bat_priv->dat.hash->table[i]; | ||
95 | list_lock = &bat_priv->dat.hash->list_locks[i]; | ||
96 | |||
97 | spin_lock_bh(list_lock); | ||
98 | hlist_for_each_entry_safe(dat_entry, node, node_tmp, head, | ||
99 | hash_entry) { | ||
100 | /* if an helper function has been passed as parameter, | ||
101 | * ask it if the entry has to be purged or not | ||
102 | */ | ||
103 | if (to_purge && !to_purge(dat_entry)) | ||
104 | continue; | ||
105 | |||
106 | hlist_del_rcu(node); | ||
107 | batadv_dat_entry_free_ref(dat_entry); | ||
108 | } | ||
109 | spin_unlock_bh(list_lock); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * batadv_dat_purge - periodic task that deletes old entries from the local DAT | ||
115 | * hash table | ||
116 | * @work: kernel work struct | ||
117 | */ | ||
118 | static void batadv_dat_purge(struct work_struct *work) | ||
119 | { | ||
120 | struct delayed_work *delayed_work; | ||
121 | struct batadv_priv_dat *priv_dat; | ||
122 | struct batadv_priv *bat_priv; | ||
123 | |||
124 | delayed_work = container_of(work, struct delayed_work, work); | ||
125 | priv_dat = container_of(delayed_work, struct batadv_priv_dat, work); | ||
126 | bat_priv = container_of(priv_dat, struct batadv_priv, dat); | ||
127 | |||
128 | __batadv_dat_purge(bat_priv, batadv_dat_to_purge); | ||
129 | batadv_dat_start_timer(bat_priv); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * batadv_compare_dat - comparing function used in the local DAT hash table | ||
134 | * @node: node in the local table | ||
135 | * @data2: second object to compare the node to | ||
136 | * | ||
137 | * Returns 1 if the two entry are the same, 0 otherwise | ||
138 | */ | ||
139 | static int batadv_compare_dat(const struct hlist_node *node, const void *data2) | ||
140 | { | ||
141 | const void *data1 = container_of(node, struct batadv_dat_entry, | ||
142 | hash_entry); | ||
143 | |||
144 | return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * batadv_arp_hw_src - extract the hw_src field from an ARP packet | ||
149 | * @skb: ARP packet | ||
150 | * @hdr_size: size of the possible header before the ARP packet | ||
151 | * | ||
152 | * Returns the value of the hw_src field in the ARP packet | ||
153 | */ | ||
154 | static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) | ||
155 | { | ||
156 | uint8_t *addr; | ||
157 | |||
158 | addr = (uint8_t *)(skb->data + hdr_size); | ||
159 | addr += ETH_HLEN + sizeof(struct arphdr); | ||
160 | |||
161 | return addr; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * batadv_arp_ip_src - extract the ip_src field from an ARP packet | ||
166 | * @skb: ARP packet | ||
167 | * @hdr_size: size of the possible header before the ARP packet | ||
168 | * | ||
169 | * Returns the value of the ip_src field in the ARP packet | ||
170 | */ | ||
171 | static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) | ||
172 | { | ||
173 | return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * batadv_arp_hw_dst - extract the hw_dst field from an ARP packet | ||
178 | * @skb: ARP packet | ||
179 | * @hdr_size: size of the possible header before the ARP packet | ||
180 | * | ||
181 | * Returns the value of the hw_dst field in the ARP packet | ||
182 | */ | ||
183 | static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) | ||
184 | { | ||
185 | return batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN + 4; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * batadv_arp_ip_dst - extract the ip_dst field from an ARP packet | ||
190 | * @skb: ARP packet | ||
191 | * @hdr_size: size of the possible header before the ARP packet | ||
192 | * | ||
193 | * Returns the value of the ip_dst field in the ARP packet | ||
194 | */ | ||
195 | static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) | ||
196 | { | ||
197 | return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4); | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * batadv_hash_dat - compute the hash value for an IP address | ||
202 | * @data: data to hash | ||
203 | * @size: size of the hash table | ||
204 | * | ||
205 | * Returns the selected index in the hash table for the given data | ||
206 | */ | ||
207 | static uint32_t batadv_hash_dat(const void *data, uint32_t size) | ||
208 | { | ||
209 | const unsigned char *key = data; | ||
210 | uint32_t hash = 0; | ||
211 | size_t i; | ||
212 | |||
213 | for (i = 0; i < 4; i++) { | ||
214 | hash += key[i]; | ||
215 | hash += (hash << 10); | ||
216 | hash ^= (hash >> 6); | ||
217 | } | ||
218 | |||
219 | hash += (hash << 3); | ||
220 | hash ^= (hash >> 11); | ||
221 | hash += (hash << 15); | ||
222 | |||
223 | return hash % size; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * batadv_dat_entry_hash_find - looks for a given dat_entry in the local hash | ||
228 | * table | ||
229 | * @bat_priv: the bat priv with all the soft interface information | ||
230 | * @ip: search key | ||
231 | * | ||
232 | * Returns the dat_entry if found, NULL otherwise | ||
233 | */ | ||
234 | static struct batadv_dat_entry * | ||
235 | batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip) | ||
236 | { | ||
237 | struct hlist_head *head; | ||
238 | struct hlist_node *node; | ||
239 | struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL; | ||
240 | struct batadv_hashtable *hash = bat_priv->dat.hash; | ||
241 | uint32_t index; | ||
242 | |||
243 | if (!hash) | ||
244 | return NULL; | ||
245 | |||
246 | index = batadv_hash_dat(&ip, hash->size); | ||
247 | head = &hash->table[index]; | ||
248 | |||
249 | rcu_read_lock(); | ||
250 | hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) { | ||
251 | if (dat_entry->ip != ip) | ||
252 | continue; | ||
253 | |||
254 | if (!atomic_inc_not_zero(&dat_entry->refcount)) | ||
255 | continue; | ||
256 | |||
257 | dat_entry_tmp = dat_entry; | ||
258 | break; | ||
259 | } | ||
260 | rcu_read_unlock(); | ||
261 | |||
262 | return dat_entry_tmp; | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * batadv_dat_entry_add - add a new dat entry or update it if already exists | ||
267 | * @bat_priv: the bat priv with all the soft interface information | ||
268 | * @ip: ipv4 to add/edit | ||
269 | * @mac_addr: mac address to assign to the given ipv4 | ||
270 | */ | ||
271 | static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip, | ||
272 | uint8_t *mac_addr) | ||
273 | { | ||
274 | struct batadv_dat_entry *dat_entry; | ||
275 | int hash_added; | ||
276 | |||
277 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip); | ||
278 | /* if this entry is already known, just update it */ | ||
279 | if (dat_entry) { | ||
280 | if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr)) | ||
281 | memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); | ||
282 | dat_entry->last_update = jiffies; | ||
283 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
284 | "Entry updated: %pI4 %pM\n", &dat_entry->ip, | ||
285 | dat_entry->mac_addr); | ||
286 | goto out; | ||
287 | } | ||
288 | |||
289 | dat_entry = kmalloc(sizeof(*dat_entry), GFP_ATOMIC); | ||
290 | if (!dat_entry) | ||
291 | goto out; | ||
292 | |||
293 | dat_entry->ip = ip; | ||
294 | memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); | ||
295 | dat_entry->last_update = jiffies; | ||
296 | atomic_set(&dat_entry->refcount, 2); | ||
297 | |||
298 | hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat, | ||
299 | batadv_hash_dat, &dat_entry->ip, | ||
300 | &dat_entry->hash_entry); | ||
301 | |||
302 | if (unlikely(hash_added != 0)) { | ||
303 | /* remove the reference for the hash */ | ||
304 | batadv_dat_entry_free_ref(dat_entry); | ||
305 | goto out; | ||
306 | } | ||
307 | |||
308 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n", | ||
309 | &dat_entry->ip, dat_entry->mac_addr); | ||
310 | |||
311 | out: | ||
312 | if (dat_entry) | ||
313 | batadv_dat_entry_free_ref(dat_entry); | ||
314 | } | ||
315 | |||
316 | #ifdef CONFIG_BATMAN_ADV_DEBUG | ||
317 | |||
318 | /** | ||
319 | * batadv_dbg_arp - print a debug message containing all the ARP packet details | ||
320 | * @bat_priv: the bat priv with all the soft interface information | ||
321 | * @skb: ARP packet | ||
322 | * @type: ARP type | ||
323 | * @hdr_size: size of the possible header before the ARP packet | ||
324 | * @msg: message to print together with the debugging information | ||
325 | */ | ||
326 | static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
327 | uint16_t type, int hdr_size, char *msg) | ||
328 | { | ||
329 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; | ||
330 | struct batadv_bcast_packet *bcast_pkt; | ||
331 | uint8_t *orig_addr; | ||
332 | __be32 ip_src, ip_dst; | ||
333 | |||
334 | if (msg) | ||
335 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg); | ||
336 | |||
337 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
338 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
339 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
340 | "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n", | ||
341 | batadv_arp_hw_src(skb, hdr_size), &ip_src, | ||
342 | batadv_arp_hw_dst(skb, hdr_size), &ip_dst); | ||
343 | |||
344 | if (hdr_size == 0) | ||
345 | return; | ||
346 | |||
347 | /* if the ARP packet is encapsulated in a batman packet, let's print | ||
348 | * some debug messages | ||
349 | */ | ||
350 | unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; | ||
351 | |||
352 | switch (unicast_4addr_packet->u.header.packet_type) { | ||
353 | case BATADV_UNICAST: | ||
354 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
355 | "* encapsulated within a UNICAST packet\n"); | ||
356 | break; | ||
357 | case BATADV_UNICAST_4ADDR: | ||
358 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
359 | "* encapsulated within a UNICAST_4ADDR packet (src: %pM)\n", | ||
360 | unicast_4addr_packet->src); | ||
361 | switch (unicast_4addr_packet->subtype) { | ||
362 | case BATADV_P_DAT_DHT_PUT: | ||
363 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_PUT\n"); | ||
364 | break; | ||
365 | case BATADV_P_DAT_DHT_GET: | ||
366 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_GET\n"); | ||
367 | break; | ||
368 | case BATADV_P_DAT_CACHE_REPLY: | ||
369 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
370 | "* type: DAT_CACHE_REPLY\n"); | ||
371 | break; | ||
372 | case BATADV_P_DATA: | ||
373 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DATA\n"); | ||
374 | break; | ||
375 | default: | ||
376 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n", | ||
377 | unicast_4addr_packet->u.header.packet_type); | ||
378 | } | ||
379 | break; | ||
380 | case BATADV_BCAST: | ||
381 | bcast_pkt = (struct batadv_bcast_packet *)unicast_4addr_packet; | ||
382 | orig_addr = bcast_pkt->orig; | ||
383 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
384 | "* encapsulated within a BCAST packet (src: %pM)\n", | ||
385 | orig_addr); | ||
386 | break; | ||
387 | default: | ||
388 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
389 | "* encapsulated within an unknown packet type (0x%x)\n", | ||
390 | unicast_4addr_packet->u.header.packet_type); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | #else | ||
395 | |||
396 | static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
397 | uint16_t type, int hdr_size, char *msg) | ||
398 | { | ||
399 | } | ||
400 | |||
401 | #endif /* CONFIG_BATMAN_ADV_DEBUG */ | ||
402 | |||
403 | /** | ||
404 | * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate | ||
405 | * @res: the array with the already selected candidates | ||
406 | * @select: number of already selected candidates | ||
407 | * @tmp_max: address of the currently evaluated node | ||
408 | * @max: current round max address | ||
409 | * @last_max: address of the last selected candidate | ||
410 | * @candidate: orig_node under evaluation | ||
411 | * @max_orig_node: last selected candidate | ||
412 | * | ||
413 | * Returns true if the node has been elected as next candidate or false othrwise | ||
414 | */ | ||
415 | static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res, | ||
416 | int select, batadv_dat_addr_t tmp_max, | ||
417 | batadv_dat_addr_t max, | ||
418 | batadv_dat_addr_t last_max, | ||
419 | struct batadv_orig_node *candidate, | ||
420 | struct batadv_orig_node *max_orig_node) | ||
421 | { | ||
422 | bool ret = false; | ||
423 | int j; | ||
424 | |||
425 | /* Check if this node has already been selected... */ | ||
426 | for (j = 0; j < select; j++) | ||
427 | if (res[j].orig_node == candidate) | ||
428 | break; | ||
429 | /* ..and possibly skip it */ | ||
430 | if (j < select) | ||
431 | goto out; | ||
432 | /* sanity check: has it already been selected? This should not happen */ | ||
433 | if (tmp_max > last_max) | ||
434 | goto out; | ||
435 | /* check if during this iteration an originator with a closer dht | ||
436 | * address has already been found | ||
437 | */ | ||
438 | if (tmp_max < max) | ||
439 | goto out; | ||
440 | /* this is an hash collision with the temporary selected node. Choose | ||
441 | * the one with the lowest address | ||
442 | */ | ||
443 | if ((tmp_max == max) && | ||
444 | (batadv_compare_eth(candidate->orig, max_orig_node->orig) > 0)) | ||
445 | goto out; | ||
446 | |||
447 | ret = true; | ||
448 | out: | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | /** | ||
453 | * batadv_choose_next_candidate - select the next DHT candidate | ||
454 | * @bat_priv: the bat priv with all the soft interface information | ||
455 | * @cands: candidates array | ||
456 | * @select: number of candidates already present in the array | ||
457 | * @ip_key: key to look up in the DHT | ||
458 | * @last_max: pointer where the address of the selected candidate will be saved | ||
459 | */ | ||
460 | static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, | ||
461 | struct batadv_dat_candidate *cands, | ||
462 | int select, batadv_dat_addr_t ip_key, | ||
463 | batadv_dat_addr_t *last_max) | ||
464 | { | ||
465 | batadv_dat_addr_t max = 0, tmp_max = 0; | ||
466 | struct batadv_orig_node *orig_node, *max_orig_node = NULL; | ||
467 | struct batadv_hashtable *hash = bat_priv->orig_hash; | ||
468 | struct hlist_node *node; | ||
469 | struct hlist_head *head; | ||
470 | int i; | ||
471 | |||
472 | /* if no node is eligible as candidate, leave the candidate type as | ||
473 | * NOT_FOUND | ||
474 | */ | ||
475 | cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND; | ||
476 | |||
477 | /* iterate over the originator list and find the node with closest | ||
478 | * dat_address which has not been selected yet | ||
479 | */ | ||
480 | for (i = 0; i < hash->size; i++) { | ||
481 | head = &hash->table[i]; | ||
482 | |||
483 | rcu_read_lock(); | ||
484 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | ||
485 | /* the dht space is a ring and addresses are unsigned */ | ||
486 | tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr + | ||
487 | ip_key; | ||
488 | |||
489 | if (!batadv_is_orig_node_eligible(cands, select, | ||
490 | tmp_max, max, | ||
491 | *last_max, orig_node, | ||
492 | max_orig_node)) | ||
493 | continue; | ||
494 | |||
495 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
496 | continue; | ||
497 | |||
498 | max = tmp_max; | ||
499 | if (max_orig_node) | ||
500 | batadv_orig_node_free_ref(max_orig_node); | ||
501 | max_orig_node = orig_node; | ||
502 | } | ||
503 | rcu_read_unlock(); | ||
504 | } | ||
505 | if (max_orig_node) { | ||
506 | cands[select].type = BATADV_DAT_CANDIDATE_ORIG; | ||
507 | cands[select].orig_node = max_orig_node; | ||
508 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
509 | "dat_select_candidates() %d: selected %pM addr=%u dist=%u\n", | ||
510 | select, max_orig_node->orig, max_orig_node->dat_addr, | ||
511 | max); | ||
512 | } | ||
513 | *last_max = max; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * batadv_dat_select_candidates - selects the nodes which the DHT message has to | ||
518 | * be sent to | ||
519 | * @bat_priv: the bat priv with all the soft interface information | ||
520 | * @ip_dst: ipv4 to look up in the DHT | ||
521 | * | ||
522 | * An originator O is selected if and only if its DHT_ID value is one of three | ||
523 | * closest values (from the LEFT, with wrap around if needed) then the hash | ||
524 | * value of the key. ip_dst is the key. | ||
525 | * | ||
526 | * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM | ||
527 | */ | ||
528 | static struct batadv_dat_candidate * | ||
529 | batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | ||
530 | { | ||
531 | int select; | ||
532 | batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key; | ||
533 | struct batadv_dat_candidate *res; | ||
534 | |||
535 | if (!bat_priv->orig_hash) | ||
536 | return NULL; | ||
537 | |||
538 | res = kmalloc(BATADV_DAT_CANDIDATES_NUM * sizeof(*res), GFP_ATOMIC); | ||
539 | if (!res) | ||
540 | return NULL; | ||
541 | |||
542 | ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst, | ||
543 | BATADV_DAT_ADDR_MAX); | ||
544 | |||
545 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
546 | "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst, | ||
547 | ip_key); | ||
548 | |||
549 | for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++) | ||
550 | batadv_choose_next_candidate(bat_priv, res, select, ip_key, | ||
551 | &last_max); | ||
552 | |||
553 | return res; | ||
554 | } | ||
555 | |||
556 | /** | ||
557 | * batadv_dat_send_data - send a payload to the selected candidates | ||
558 | * @bat_priv: the bat priv with all the soft interface information | ||
559 | * @skb: payload to send | ||
560 | * @ip: the DHT key | ||
561 | * @packet_subtype: unicast4addr packet subtype to use | ||
562 | * | ||
563 | * In this function the skb is copied by means of pskb_copy() and is sent as | ||
564 | * unicast packet to each of the selected candidates | ||
565 | * | ||
566 | * Returns true if the packet is sent to at least one candidate, false otherwise | ||
567 | */ | ||
568 | static bool batadv_dat_send_data(struct batadv_priv *bat_priv, | ||
569 | struct sk_buff *skb, __be32 ip, | ||
570 | int packet_subtype) | ||
571 | { | ||
572 | int i; | ||
573 | bool ret = false; | ||
574 | int send_status; | ||
575 | struct batadv_neigh_node *neigh_node = NULL; | ||
576 | struct sk_buff *tmp_skb; | ||
577 | struct batadv_dat_candidate *cand; | ||
578 | |||
579 | cand = batadv_dat_select_candidates(bat_priv, ip); | ||
580 | if (!cand) | ||
581 | goto out; | ||
582 | |||
583 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip); | ||
584 | |||
585 | for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) { | ||
586 | if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND) | ||
587 | continue; | ||
588 | |||
589 | neigh_node = batadv_orig_node_get_router(cand[i].orig_node); | ||
590 | if (!neigh_node) | ||
591 | goto free_orig; | ||
592 | |||
593 | tmp_skb = pskb_copy(skb, GFP_ATOMIC); | ||
594 | if (!batadv_unicast_4addr_prepare_skb(bat_priv, tmp_skb, | ||
595 | cand[i].orig_node, | ||
596 | packet_subtype)) { | ||
597 | kfree_skb(tmp_skb); | ||
598 | goto free_neigh; | ||
599 | } | ||
600 | |||
601 | send_status = batadv_send_skb_packet(tmp_skb, | ||
602 | neigh_node->if_incoming, | ||
603 | neigh_node->addr); | ||
604 | if (send_status == NET_XMIT_SUCCESS) { | ||
605 | /* count the sent packet */ | ||
606 | switch (packet_subtype) { | ||
607 | case BATADV_P_DAT_DHT_GET: | ||
608 | batadv_inc_counter(bat_priv, | ||
609 | BATADV_CNT_DAT_GET_TX); | ||
610 | break; | ||
611 | case BATADV_P_DAT_DHT_PUT: | ||
612 | batadv_inc_counter(bat_priv, | ||
613 | BATADV_CNT_DAT_PUT_TX); | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | /* packet sent to a candidate: return true */ | ||
618 | ret = true; | ||
619 | } | ||
620 | free_neigh: | ||
621 | batadv_neigh_node_free_ref(neigh_node); | ||
622 | free_orig: | ||
623 | batadv_orig_node_free_ref(cand[i].orig_node); | ||
624 | } | ||
625 | |||
626 | out: | ||
627 | kfree(cand); | ||
628 | return ret; | ||
629 | } | ||
630 | |||
631 | /** | ||
632 | * batadv_dat_hash_free - free the local DAT hash table | ||
633 | * @bat_priv: the bat priv with all the soft interface information | ||
634 | */ | ||
635 | static void batadv_dat_hash_free(struct batadv_priv *bat_priv) | ||
636 | { | ||
637 | if (!bat_priv->dat.hash) | ||
638 | return; | ||
639 | |||
640 | __batadv_dat_purge(bat_priv, NULL); | ||
641 | |||
642 | batadv_hash_destroy(bat_priv->dat.hash); | ||
643 | |||
644 | bat_priv->dat.hash = NULL; | ||
645 | } | ||
646 | |||
647 | /** | ||
648 | * batadv_dat_init - initialise the DAT internals | ||
649 | * @bat_priv: the bat priv with all the soft interface information | ||
650 | */ | ||
651 | int batadv_dat_init(struct batadv_priv *bat_priv) | ||
652 | { | ||
653 | if (bat_priv->dat.hash) | ||
654 | return 0; | ||
655 | |||
656 | bat_priv->dat.hash = batadv_hash_new(1024); | ||
657 | |||
658 | if (!bat_priv->dat.hash) | ||
659 | return -ENOMEM; | ||
660 | |||
661 | batadv_dat_start_timer(bat_priv); | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | /** | ||
667 | * batadv_dat_free - free the DAT internals | ||
668 | * @bat_priv: the bat priv with all the soft interface information | ||
669 | */ | ||
670 | void batadv_dat_free(struct batadv_priv *bat_priv) | ||
671 | { | ||
672 | cancel_delayed_work_sync(&bat_priv->dat.work); | ||
673 | |||
674 | batadv_dat_hash_free(bat_priv); | ||
675 | } | ||
676 | |||
677 | /** | ||
678 | * batadv_dat_cache_seq_print_text - print the local DAT hash table | ||
679 | * @seq: seq file to print on | ||
680 | * @offset: not used | ||
681 | */ | ||
682 | int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) | ||
683 | { | ||
684 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
685 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | ||
686 | struct batadv_hashtable *hash = bat_priv->dat.hash; | ||
687 | struct batadv_dat_entry *dat_entry; | ||
688 | struct batadv_hard_iface *primary_if; | ||
689 | struct hlist_node *node; | ||
690 | struct hlist_head *head; | ||
691 | unsigned long last_seen_jiffies; | ||
692 | int last_seen_msecs, last_seen_secs, last_seen_mins; | ||
693 | uint32_t i; | ||
694 | |||
695 | primary_if = batadv_seq_print_text_primary_if_get(seq); | ||
696 | if (!primary_if) | ||
697 | goto out; | ||
698 | |||
699 | seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name); | ||
700 | seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC", | ||
701 | "last-seen"); | ||
702 | |||
703 | for (i = 0; i < hash->size; i++) { | ||
704 | head = &hash->table[i]; | ||
705 | |||
706 | rcu_read_lock(); | ||
707 | hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) { | ||
708 | last_seen_jiffies = jiffies - dat_entry->last_update; | ||
709 | last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); | ||
710 | last_seen_mins = last_seen_msecs / 60000; | ||
711 | last_seen_msecs = last_seen_msecs % 60000; | ||
712 | last_seen_secs = last_seen_msecs / 1000; | ||
713 | |||
714 | seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n", | ||
715 | &dat_entry->ip, dat_entry->mac_addr, | ||
716 | last_seen_mins, last_seen_secs); | ||
717 | } | ||
718 | rcu_read_unlock(); | ||
719 | } | ||
720 | |||
721 | out: | ||
722 | if (primary_if) | ||
723 | batadv_hardif_free_ref(primary_if); | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | /** | ||
728 | * batadv_arp_get_type - parse an ARP packet and gets the type | ||
729 | * @bat_priv: the bat priv with all the soft interface information | ||
730 | * @skb: packet to analyse | ||
731 | * @hdr_size: size of the possible header before the ARP packet in the skb | ||
732 | * | ||
733 | * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise | ||
734 | */ | ||
735 | static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, | ||
736 | struct sk_buff *skb, int hdr_size) | ||
737 | { | ||
738 | struct arphdr *arphdr; | ||
739 | struct ethhdr *ethhdr; | ||
740 | __be32 ip_src, ip_dst; | ||
741 | uint16_t type = 0; | ||
742 | |||
743 | /* pull the ethernet header */ | ||
744 | if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN))) | ||
745 | goto out; | ||
746 | |||
747 | ethhdr = (struct ethhdr *)(skb->data + hdr_size); | ||
748 | |||
749 | if (ethhdr->h_proto != htons(ETH_P_ARP)) | ||
750 | goto out; | ||
751 | |||
752 | /* pull the ARP payload */ | ||
753 | if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN + | ||
754 | arp_hdr_len(skb->dev)))) | ||
755 | goto out; | ||
756 | |||
757 | arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN); | ||
758 | |||
759 | /* Check whether the ARP packet carries a valid | ||
760 | * IP information | ||
761 | */ | ||
762 | if (arphdr->ar_hrd != htons(ARPHRD_ETHER)) | ||
763 | goto out; | ||
764 | |||
765 | if (arphdr->ar_pro != htons(ETH_P_IP)) | ||
766 | goto out; | ||
767 | |||
768 | if (arphdr->ar_hln != ETH_ALEN) | ||
769 | goto out; | ||
770 | |||
771 | if (arphdr->ar_pln != 4) | ||
772 | goto out; | ||
773 | |||
774 | /* Check for bad reply/request. If the ARP message is not sane, DAT | ||
775 | * will simply ignore it | ||
776 | */ | ||
777 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
778 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
779 | if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) || | ||
780 | ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst)) | ||
781 | goto out; | ||
782 | |||
783 | type = ntohs(arphdr->ar_op); | ||
784 | out: | ||
785 | return type; | ||
786 | } | ||
787 | |||
788 | /** | ||
789 | * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to | ||
790 | * answer using DAT | ||
791 | * @bat_priv: the bat priv with all the soft interface information | ||
792 | * @skb: packet to check | ||
793 | * | ||
794 | * Returns true if the message has been sent to the dht candidates, false | ||
795 | * otherwise. In case of true the message has to be enqueued to permit the | ||
796 | * fallback | ||
797 | */ | ||
798 | bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | ||
799 | struct sk_buff *skb) | ||
800 | { | ||
801 | uint16_t type = 0; | ||
802 | __be32 ip_dst, ip_src; | ||
803 | uint8_t *hw_src; | ||
804 | bool ret = false; | ||
805 | struct batadv_dat_entry *dat_entry = NULL; | ||
806 | struct sk_buff *skb_new; | ||
807 | struct batadv_hard_iface *primary_if = NULL; | ||
808 | |||
809 | if (!atomic_read(&bat_priv->distributed_arp_table)) | ||
810 | goto out; | ||
811 | |||
812 | type = batadv_arp_get_type(bat_priv, skb, 0); | ||
813 | /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast | ||
814 | * message to the selected DHT candidates | ||
815 | */ | ||
816 | if (type != ARPOP_REQUEST) | ||
817 | goto out; | ||
818 | |||
819 | batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REQUEST"); | ||
820 | |||
821 | ip_src = batadv_arp_ip_src(skb, 0); | ||
822 | hw_src = batadv_arp_hw_src(skb, 0); | ||
823 | ip_dst = batadv_arp_ip_dst(skb, 0); | ||
824 | |||
825 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
826 | |||
827 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | ||
828 | if (dat_entry) { | ||
829 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
830 | if (!primary_if) | ||
831 | goto out; | ||
832 | |||
833 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, | ||
834 | primary_if->soft_iface, ip_dst, hw_src, | ||
835 | dat_entry->mac_addr, hw_src); | ||
836 | if (!skb_new) | ||
837 | goto out; | ||
838 | |||
839 | skb_reset_mac_header(skb_new); | ||
840 | skb_new->protocol = eth_type_trans(skb_new, | ||
841 | primary_if->soft_iface); | ||
842 | bat_priv->stats.rx_packets++; | ||
843 | bat_priv->stats.rx_bytes += skb->len + ETH_HLEN; | ||
844 | primary_if->soft_iface->last_rx = jiffies; | ||
845 | |||
846 | netif_rx(skb_new); | ||
847 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n"); | ||
848 | ret = true; | ||
849 | } else { | ||
850 | /* Send the request on the DHT */ | ||
851 | ret = batadv_dat_send_data(bat_priv, skb, ip_dst, | ||
852 | BATADV_P_DAT_DHT_GET); | ||
853 | } | ||
854 | out: | ||
855 | if (dat_entry) | ||
856 | batadv_dat_entry_free_ref(dat_entry); | ||
857 | if (primary_if) | ||
858 | batadv_hardif_free_ref(primary_if); | ||
859 | return ret; | ||
860 | } | ||
861 | |||
862 | /** | ||
863 | * batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to | ||
864 | * answer using the local DAT storage | ||
865 | * @bat_priv: the bat priv with all the soft interface information | ||
866 | * @skb: packet to check | ||
867 | * @hdr_size: size of the encapsulation header | ||
868 | * | ||
869 | * Returns true if the request has been answered, false otherwise | ||
870 | */ | ||
871 | bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, | ||
872 | struct sk_buff *skb, int hdr_size) | ||
873 | { | ||
874 | uint16_t type; | ||
875 | __be32 ip_src, ip_dst; | ||
876 | uint8_t *hw_src; | ||
877 | struct sk_buff *skb_new; | ||
878 | struct batadv_hard_iface *primary_if = NULL; | ||
879 | struct batadv_dat_entry *dat_entry = NULL; | ||
880 | bool ret = false; | ||
881 | int err; | ||
882 | |||
883 | if (!atomic_read(&bat_priv->distributed_arp_table)) | ||
884 | goto out; | ||
885 | |||
886 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); | ||
887 | if (type != ARPOP_REQUEST) | ||
888 | goto out; | ||
889 | |||
890 | hw_src = batadv_arp_hw_src(skb, hdr_size); | ||
891 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
892 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
893 | |||
894 | batadv_dbg_arp(bat_priv, skb, type, hdr_size, | ||
895 | "Parsing incoming ARP REQUEST"); | ||
896 | |||
897 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
898 | |||
899 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | ||
900 | if (!dat_entry) | ||
901 | goto out; | ||
902 | |||
903 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
904 | if (!primary_if) | ||
905 | goto out; | ||
906 | |||
907 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, | ||
908 | primary_if->soft_iface, ip_dst, hw_src, | ||
909 | dat_entry->mac_addr, hw_src); | ||
910 | |||
911 | if (!skb_new) | ||
912 | goto out; | ||
913 | |||
914 | /* to preserve backwards compatibility, here the node has to answer | ||
915 | * using the same packet type it received for the request. This is due | ||
916 | * to that if a node is not using the 4addr packet format it may not | ||
917 | * support it. | ||
918 | */ | ||
919 | if (hdr_size == sizeof(struct batadv_unicast_4addr_packet)) | ||
920 | err = batadv_unicast_4addr_send_skb(bat_priv, skb_new, | ||
921 | BATADV_P_DAT_CACHE_REPLY); | ||
922 | else | ||
923 | err = batadv_unicast_send_skb(bat_priv, skb_new); | ||
924 | |||
925 | if (!err) { | ||
926 | batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX); | ||
927 | ret = true; | ||
928 | } | ||
929 | out: | ||
930 | if (dat_entry) | ||
931 | batadv_dat_entry_free_ref(dat_entry); | ||
932 | if (primary_if) | ||
933 | batadv_hardif_free_ref(primary_if); | ||
934 | if (ret) | ||
935 | kfree_skb(skb); | ||
936 | return ret; | ||
937 | } | ||
938 | |||
939 | /** | ||
940 | * batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT | ||
941 | * @bat_priv: the bat priv with all the soft interface information | ||
942 | * @skb: packet to check | ||
943 | */ | ||
944 | void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | ||
945 | struct sk_buff *skb) | ||
946 | { | ||
947 | uint16_t type; | ||
948 | __be32 ip_src, ip_dst; | ||
949 | uint8_t *hw_src, *hw_dst; | ||
950 | |||
951 | if (!atomic_read(&bat_priv->distributed_arp_table)) | ||
952 | return; | ||
953 | |||
954 | type = batadv_arp_get_type(bat_priv, skb, 0); | ||
955 | if (type != ARPOP_REPLY) | ||
956 | return; | ||
957 | |||
958 | batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REPLY"); | ||
959 | |||
960 | hw_src = batadv_arp_hw_src(skb, 0); | ||
961 | ip_src = batadv_arp_ip_src(skb, 0); | ||
962 | hw_dst = batadv_arp_hw_dst(skb, 0); | ||
963 | ip_dst = batadv_arp_ip_dst(skb, 0); | ||
964 | |||
965 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
966 | batadv_dat_entry_add(bat_priv, ip_dst, hw_dst); | ||
967 | |||
968 | /* Send the ARP reply to the candidates for both the IP addresses that | ||
969 | * the node got within the ARP reply | ||
970 | */ | ||
971 | batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT); | ||
972 | batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT); | ||
973 | } | ||
974 | /** | ||
975 | * batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local | ||
976 | * DAT storage only | ||
977 | * @bat_priv: the bat priv with all the soft interface information | ||
978 | * @skb: packet to check | ||
979 | * @hdr_size: siaze of the encapsulation header | ||
980 | */ | ||
981 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | ||
982 | struct sk_buff *skb, int hdr_size) | ||
983 | { | ||
984 | uint16_t type; | ||
985 | __be32 ip_src, ip_dst; | ||
986 | uint8_t *hw_src, *hw_dst; | ||
987 | bool ret = false; | ||
988 | |||
989 | if (!atomic_read(&bat_priv->distributed_arp_table)) | ||
990 | goto out; | ||
991 | |||
992 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); | ||
993 | if (type != ARPOP_REPLY) | ||
994 | goto out; | ||
995 | |||
996 | batadv_dbg_arp(bat_priv, skb, type, hdr_size, | ||
997 | "Parsing incoming ARP REPLY"); | ||
998 | |||
999 | hw_src = batadv_arp_hw_src(skb, hdr_size); | ||
1000 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
1001 | hw_dst = batadv_arp_hw_dst(skb, hdr_size); | ||
1002 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
1003 | |||
1004 | /* Update our internal cache with both the IP addresses the node got | ||
1005 | * within the ARP reply | ||
1006 | */ | ||
1007 | batadv_dat_entry_add(bat_priv, ip_src, hw_src); | ||
1008 | batadv_dat_entry_add(bat_priv, ip_dst, hw_dst); | ||
1009 | |||
1010 | /* if this REPLY is directed to a client of mine, let's deliver the | ||
1011 | * packet to the interface | ||
1012 | */ | ||
1013 | ret = !batadv_is_my_client(bat_priv, hw_dst); | ||
1014 | out: | ||
1015 | /* if ret == false -> packet has to be delivered to the interface */ | ||
1016 | return ret; | ||
1017 | } | ||
1018 | |||
1019 | /** | ||
1020 | * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped | ||
1021 | * (because the node has already got the reply via DAT) or not | ||
1022 | * @bat_priv: the bat priv with all the soft interface information | ||
1023 | * @forw_packet: the broadcast packet | ||
1024 | * | ||
1025 | * Returns true if the node can drop the packet, false otherwise | ||
1026 | */ | ||
1027 | bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, | ||
1028 | struct batadv_forw_packet *forw_packet) | ||
1029 | { | ||
1030 | uint16_t type; | ||
1031 | __be32 ip_dst; | ||
1032 | struct batadv_dat_entry *dat_entry = NULL; | ||
1033 | bool ret = false; | ||
1034 | const size_t bcast_len = sizeof(struct batadv_bcast_packet); | ||
1035 | |||
1036 | if (!atomic_read(&bat_priv->distributed_arp_table)) | ||
1037 | goto out; | ||
1038 | |||
1039 | /* If this packet is an ARP_REQUEST and the node already has the | ||
1040 | * information that it is going to ask, then the packet can be dropped | ||
1041 | */ | ||
1042 | if (forw_packet->num_packets) | ||
1043 | goto out; | ||
1044 | |||
1045 | type = batadv_arp_get_type(bat_priv, forw_packet->skb, bcast_len); | ||
1046 | if (type != ARPOP_REQUEST) | ||
1047 | goto out; | ||
1048 | |||
1049 | ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len); | ||
1050 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | ||
1051 | /* check if the node already got this entry */ | ||
1052 | if (!dat_entry) { | ||
1053 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
1054 | "ARP Request for %pI4: fallback\n", &ip_dst); | ||
1055 | goto out; | ||
1056 | } | ||
1057 | |||
1058 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
1059 | "ARP Request for %pI4: fallback prevented\n", &ip_dst); | ||
1060 | ret = true; | ||
1061 | |||
1062 | out: | ||
1063 | if (dat_entry) | ||
1064 | batadv_dat_entry_free_ref(dat_entry); | ||
1065 | return ret; | ||
1066 | } | ||
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h new file mode 100644 index 000000000000..d060c033e7de --- /dev/null +++ b/net/batman-adv/distributed-arp-table.h | |||
@@ -0,0 +1,167 @@ | |||
1 | /* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors: | ||
2 | * | ||
3 | * Antonio Quartulli | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of version 2 of the GNU General Public | ||
7 | * License as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | * 02110-1301, USA | ||
18 | */ | ||
19 | |||
20 | #ifndef _NET_BATMAN_ADV_ARP_H_ | ||
21 | #define _NET_BATMAN_ADV_ARP_H_ | ||
22 | |||
23 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
24 | |||
25 | #include "types.h" | ||
26 | #include "originator.h" | ||
27 | |||
28 | #include <linux/if_arp.h> | ||
29 | |||
30 | #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) | ||
31 | |||
32 | bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | ||
33 | struct sk_buff *skb); | ||
34 | bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, | ||
35 | struct sk_buff *skb, int hdr_size); | ||
36 | void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | ||
37 | struct sk_buff *skb); | ||
38 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | ||
39 | struct sk_buff *skb, int hdr_size); | ||
40 | bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, | ||
41 | struct batadv_forw_packet *forw_packet); | ||
42 | |||
43 | /** | ||
44 | * batadv_dat_init_orig_node_addr - assign a DAT address to the orig_node | ||
45 | * @orig_node: the node to assign the DAT address to | ||
46 | */ | ||
47 | static inline void | ||
48 | batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node) | ||
49 | { | ||
50 | uint32_t addr; | ||
51 | |||
52 | addr = batadv_choose_orig(orig_node->orig, BATADV_DAT_ADDR_MAX); | ||
53 | orig_node->dat_addr = (batadv_dat_addr_t)addr; | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * batadv_dat_init_own_addr - assign a DAT address to the node itself | ||
58 | * @bat_priv: the bat priv with all the soft interface information | ||
59 | * @primary_if: a pointer to the primary interface | ||
60 | */ | ||
61 | static inline void | ||
62 | batadv_dat_init_own_addr(struct batadv_priv *bat_priv, | ||
63 | struct batadv_hard_iface *primary_if) | ||
64 | { | ||
65 | uint32_t addr; | ||
66 | |||
67 | addr = batadv_choose_orig(primary_if->net_dev->dev_addr, | ||
68 | BATADV_DAT_ADDR_MAX); | ||
69 | |||
70 | bat_priv->dat.addr = (batadv_dat_addr_t)addr; | ||
71 | } | ||
72 | |||
73 | int batadv_dat_init(struct batadv_priv *bat_priv); | ||
74 | void batadv_dat_free(struct batadv_priv *bat_priv); | ||
75 | int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset); | ||
76 | |||
77 | /** | ||
78 | * batadv_dat_inc_counter - increment the correct DAT packet counter | ||
79 | * @bat_priv: the bat priv with all the soft interface information | ||
80 | * @subtype: the 4addr subtype of the packet to be counted | ||
81 | * | ||
82 | * Updates the ethtool statistics for the received packet if it is a DAT subtype | ||
83 | */ | ||
84 | static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv, | ||
85 | uint8_t subtype) | ||
86 | { | ||
87 | switch (subtype) { | ||
88 | case BATADV_P_DAT_DHT_GET: | ||
89 | batadv_inc_counter(bat_priv, | ||
90 | BATADV_CNT_DAT_GET_RX); | ||
91 | break; | ||
92 | case BATADV_P_DAT_DHT_PUT: | ||
93 | batadv_inc_counter(bat_priv, | ||
94 | BATADV_CNT_DAT_PUT_RX); | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | #else | ||
100 | |||
101 | static inline bool | ||
102 | batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | ||
103 | struct sk_buff *skb) | ||
104 | { | ||
105 | return false; | ||
106 | } | ||
107 | |||
108 | static inline bool | ||
109 | batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, | ||
110 | struct sk_buff *skb, int hdr_size) | ||
111 | { | ||
112 | return false; | ||
113 | } | ||
114 | |||
115 | static inline bool | ||
116 | batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | ||
117 | struct sk_buff *skb) | ||
118 | { | ||
119 | return false; | ||
120 | } | ||
121 | |||
122 | static inline bool | ||
123 | batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | ||
124 | struct sk_buff *skb, int hdr_size) | ||
125 | { | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | static inline bool | ||
130 | batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, | ||
131 | struct batadv_forw_packet *forw_packet) | ||
132 | { | ||
133 | return false; | ||
134 | } | ||
135 | |||
136 | static inline void | ||
137 | batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node) | ||
138 | { | ||
139 | } | ||
140 | |||
141 | static inline void batadv_dat_init_own_addr(struct batadv_priv *bat_priv, | ||
142 | struct batadv_hard_iface *iface) | ||
143 | { | ||
144 | } | ||
145 | |||
146 | static inline void batadv_arp_change_timeout(struct net_device *soft_iface, | ||
147 | const char *name) | ||
148 | { | ||
149 | } | ||
150 | |||
151 | static inline int batadv_dat_init(struct batadv_priv *bat_priv) | ||
152 | { | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static inline void batadv_dat_free(struct batadv_priv *bat_priv) | ||
157 | { | ||
158 | } | ||
159 | |||
160 | static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv, | ||
161 | uint8_t subtype) | ||
162 | { | ||
163 | } | ||
164 | |||
165 | #endif /* CONFIG_BATMAN_ADV_DAT */ | ||
166 | |||
167 | #endif /* _NET_BATMAN_ADV_ARP_H_ */ | ||
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 15d67abc10a4..dd07c7e3654f 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -477,22 +477,11 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
477 | struct batadv_hard_iface *primary_if; | 477 | struct batadv_hard_iface *primary_if; |
478 | struct batadv_gw_node *gw_node; | 478 | struct batadv_gw_node *gw_node; |
479 | struct hlist_node *node; | 479 | struct hlist_node *node; |
480 | int gw_count = 0, ret = 0; | 480 | int gw_count = 0; |
481 | 481 | ||
482 | primary_if = batadv_primary_if_get_selected(bat_priv); | 482 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
483 | if (!primary_if) { | 483 | if (!primary_if) |
484 | ret = seq_printf(seq, | ||
485 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
486 | net_dev->name); | ||
487 | goto out; | 484 | goto out; |
488 | } | ||
489 | |||
490 | if (primary_if->if_status != BATADV_IF_ACTIVE) { | ||
491 | ret = seq_printf(seq, | ||
492 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
493 | net_dev->name); | ||
494 | goto out; | ||
495 | } | ||
496 | 485 | ||
497 | seq_printf(seq, | 486 | seq_printf(seq, |
498 | " %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", | 487 | " %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", |
@@ -519,7 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
519 | out: | 508 | out: |
520 | if (primary_if) | 509 | if (primary_if) |
521 | batadv_hardif_free_ref(primary_if); | 510 | batadv_hardif_free_ref(primary_if); |
522 | return ret; | 511 | return 0; |
523 | } | 512 | } |
524 | 513 | ||
525 | static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len) | 514 | static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len) |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index d112fd6750b0..365ed74f3946 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.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 "hard-interface.h" | 22 | #include "hard-interface.h" |
22 | #include "soft-interface.h" | 23 | #include "soft-interface.h" |
23 | #include "send.h" | 24 | #include "send.h" |
@@ -58,6 +59,45 @@ out: | |||
58 | return hard_iface; | 59 | return hard_iface; |
59 | } | 60 | } |
60 | 61 | ||
62 | /** | ||
63 | * batadv_is_on_batman_iface - check if a device is a batman iface descendant | ||
64 | * @net_dev: the device to check | ||
65 | * | ||
66 | * If the user creates any virtual device on top of a batman-adv interface, it | ||
67 | * is important to prevent this new interface to be used to create a new mesh | ||
68 | * network (this behaviour would lead to a batman-over-batman configuration). | ||
69 | * This function recursively checks all the fathers of the device passed as | ||
70 | * argument looking for a batman-adv soft interface. | ||
71 | * | ||
72 | * Returns true if the device is descendant of a batman-adv mesh interface (or | ||
73 | * if it is a batman-adv interface itself), false otherwise | ||
74 | */ | ||
75 | static bool batadv_is_on_batman_iface(const struct net_device *net_dev) | ||
76 | { | ||
77 | struct net_device *parent_dev; | ||
78 | bool ret; | ||
79 | |||
80 | /* check if this is a batman-adv mesh interface */ | ||
81 | if (batadv_softif_is_valid(net_dev)) | ||
82 | return true; | ||
83 | |||
84 | /* no more parents..stop recursion */ | ||
85 | if (net_dev->iflink == net_dev->ifindex) | ||
86 | return false; | ||
87 | |||
88 | /* recurse over the parent device */ | ||
89 | parent_dev = dev_get_by_index(&init_net, net_dev->iflink); | ||
90 | /* if we got a NULL parent_dev there is something broken.. */ | ||
91 | if (WARN(!parent_dev, "Cannot find parent device")) | ||
92 | return false; | ||
93 | |||
94 | ret = batadv_is_on_batman_iface(parent_dev); | ||
95 | |||
96 | if (parent_dev) | ||
97 | dev_put(parent_dev); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
61 | static int batadv_is_valid_iface(const struct net_device *net_dev) | 101 | static int batadv_is_valid_iface(const struct net_device *net_dev) |
62 | { | 102 | { |
63 | if (net_dev->flags & IFF_LOOPBACK) | 103 | if (net_dev->flags & IFF_LOOPBACK) |
@@ -70,7 +110,7 @@ static int batadv_is_valid_iface(const struct net_device *net_dev) | |||
70 | return 0; | 110 | return 0; |
71 | 111 | ||
72 | /* no batman over batman */ | 112 | /* no batman over batman */ |
73 | if (batadv_softif_is_valid(net_dev)) | 113 | if (batadv_is_on_batman_iface(net_dev)) |
74 | return 0; | 114 | return 0; |
75 | 115 | ||
76 | return 1; | 116 | return 1; |
@@ -109,6 +149,8 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv, | |||
109 | if (!primary_if) | 149 | if (!primary_if) |
110 | goto out; | 150 | goto out; |
111 | 151 | ||
152 | batadv_dat_init_own_addr(bat_priv, primary_if); | ||
153 | |||
112 | skb = bat_priv->vis.my_info->skb_packet; | 154 | skb = bat_priv->vis.my_info->skb_packet; |
113 | vis_packet = (struct batadv_vis_packet *)skb->data; | 155 | vis_packet = (struct batadv_vis_packet *)skb->data; |
114 | memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); | 156 | memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
@@ -450,8 +492,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) | |||
450 | /* This can't be called via a bat_priv callback because | 492 | /* This can't be called via a bat_priv callback because |
451 | * we have no bat_priv yet. | 493 | * we have no bat_priv yet. |
452 | */ | 494 | */ |
453 | atomic_set(&hard_iface->seqno, 1); | 495 | atomic_set(&hard_iface->bat_iv.ogm_seqno, 1); |
454 | hard_iface->packet_buff = NULL; | 496 | hard_iface->bat_iv.ogm_buff = NULL; |
455 | 497 | ||
456 | return hard_iface; | 498 | return hard_iface; |
457 | 499 | ||
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index 977de9c75fc2..e05333905afd 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h | |||
@@ -82,6 +82,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash, | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * batadv_hash_bytes - hash some bytes and add them to the previous hash | ||
86 | * @hash: previous hash value | ||
87 | * @data: data to be hashed | ||
88 | * @size: number of bytes to be hashed | ||
89 | * | ||
90 | * Returns the new hash value. | ||
91 | */ | ||
92 | static inline uint32_t batadv_hash_bytes(uint32_t hash, void *data, | ||
93 | uint32_t size) | ||
94 | { | ||
95 | const unsigned char *key = data; | ||
96 | int i; | ||
97 | |||
98 | for (i = 0; i < size; i++) { | ||
99 | hash += key[i]; | ||
100 | hash += (hash << 10); | ||
101 | hash ^= (hash >> 6); | ||
102 | } | ||
103 | return hash; | ||
104 | } | ||
105 | |||
106 | /** | ||
85 | * batadv_hash_add - adds data to the hashtable | 107 | * batadv_hash_add - adds data to the hashtable |
86 | * @hash: storage hash table | 108 | * @hash: storage hash table |
87 | * @compare: callback to determine if 2 hash elements are identical | 109 | * @compare: callback to determine if 2 hash elements are identical |
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index bde3cf747507..87ca8095b011 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c | |||
@@ -42,12 +42,16 @@ static int batadv_socket_open(struct inode *inode, struct file *file) | |||
42 | unsigned int i; | 42 | unsigned int i; |
43 | struct batadv_socket_client *socket_client; | 43 | struct batadv_socket_client *socket_client; |
44 | 44 | ||
45 | if (!try_module_get(THIS_MODULE)) | ||
46 | return -EBUSY; | ||
47 | |||
45 | nonseekable_open(inode, file); | 48 | nonseekable_open(inode, file); |
46 | 49 | ||
47 | socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL); | 50 | socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL); |
48 | 51 | if (!socket_client) { | |
49 | if (!socket_client) | 52 | module_put(THIS_MODULE); |
50 | return -ENOMEM; | 53 | return -ENOMEM; |
54 | } | ||
51 | 55 | ||
52 | for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) { | 56 | for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) { |
53 | if (!batadv_socket_client_hash[i]) { | 57 | if (!batadv_socket_client_hash[i]) { |
@@ -59,6 +63,7 @@ static int batadv_socket_open(struct inode *inode, struct file *file) | |||
59 | if (i == ARRAY_SIZE(batadv_socket_client_hash)) { | 63 | if (i == ARRAY_SIZE(batadv_socket_client_hash)) { |
60 | pr_err("Error - can't add another packet client: maximum number of clients reached\n"); | 64 | pr_err("Error - can't add another packet client: maximum number of clients reached\n"); |
61 | kfree(socket_client); | 65 | kfree(socket_client); |
66 | module_put(THIS_MODULE); | ||
62 | return -EXFULL; | 67 | return -EXFULL; |
63 | } | 68 | } |
64 | 69 | ||
@@ -71,7 +76,6 @@ static int batadv_socket_open(struct inode *inode, struct file *file) | |||
71 | 76 | ||
72 | file->private_data = socket_client; | 77 | file->private_data = socket_client; |
73 | 78 | ||
74 | batadv_inc_module_count(); | ||
75 | return 0; | 79 | return 0; |
76 | } | 80 | } |
77 | 81 | ||
@@ -96,7 +100,7 @@ static int batadv_socket_release(struct inode *inode, struct file *file) | |||
96 | spin_unlock_bh(&socket_client->lock); | 100 | spin_unlock_bh(&socket_client->lock); |
97 | 101 | ||
98 | kfree(socket_client); | 102 | kfree(socket_client); |
99 | batadv_dec_module_count(); | 103 | module_put(THIS_MODULE); |
100 | 104 | ||
101 | return 0; | 105 | return 0; |
102 | } | 106 | } |
@@ -173,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff, | |||
173 | if (len >= sizeof(struct batadv_icmp_packet_rr)) | 177 | if (len >= sizeof(struct batadv_icmp_packet_rr)) |
174 | packet_len = sizeof(struct batadv_icmp_packet_rr); | 178 | packet_len = sizeof(struct batadv_icmp_packet_rr); |
175 | 179 | ||
176 | skb = dev_alloc_skb(packet_len + ETH_HLEN); | 180 | skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN); |
177 | if (!skb) { | 181 | if (!skb) { |
178 | len = -ENOMEM; | 182 | len = -ENOMEM; |
179 | goto out; | 183 | goto out; |
180 | } | 184 | } |
181 | 185 | ||
182 | skb_reserve(skb, ETH_HLEN); | 186 | skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
183 | icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len); | 187 | icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len); |
184 | 188 | ||
185 | if (copy_from_user(icmp_packet, buff, packet_len)) { | 189 | if (copy_from_user(icmp_packet, buff, packet_len)) { |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index b4aa470bc4a6..dc33a0c484a4 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "hard-interface.h" | 29 | #include "hard-interface.h" |
30 | #include "gateway_client.h" | 30 | #include "gateway_client.h" |
31 | #include "bridge_loop_avoidance.h" | 31 | #include "bridge_loop_avoidance.h" |
32 | #include "distributed-arp-table.h" | ||
32 | #include "vis.h" | 33 | #include "vis.h" |
33 | #include "hash.h" | 34 | #include "hash.h" |
34 | #include "bat_algo.h" | 35 | #include "bat_algo.h" |
@@ -128,6 +129,10 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
128 | if (ret < 0) | 129 | if (ret < 0) |
129 | goto err; | 130 | goto err; |
130 | 131 | ||
132 | ret = batadv_dat_init(bat_priv); | ||
133 | if (ret < 0) | ||
134 | goto err; | ||
135 | |||
131 | atomic_set(&bat_priv->gw.reselect, 0); | 136 | atomic_set(&bat_priv->gw.reselect, 0); |
132 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); | 137 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); |
133 | 138 | ||
@@ -155,21 +160,13 @@ void batadv_mesh_free(struct net_device *soft_iface) | |||
155 | 160 | ||
156 | batadv_bla_free(bat_priv); | 161 | batadv_bla_free(bat_priv); |
157 | 162 | ||
163 | batadv_dat_free(bat_priv); | ||
164 | |||
158 | free_percpu(bat_priv->bat_counters); | 165 | free_percpu(bat_priv->bat_counters); |
159 | 166 | ||
160 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); | 167 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); |
161 | } | 168 | } |
162 | 169 | ||
163 | void batadv_inc_module_count(void) | ||
164 | { | ||
165 | try_module_get(THIS_MODULE); | ||
166 | } | ||
167 | |||
168 | void batadv_dec_module_count(void) | ||
169 | { | ||
170 | module_put(THIS_MODULE); | ||
171 | } | ||
172 | |||
173 | int batadv_is_my_mac(const uint8_t *addr) | 170 | int batadv_is_my_mac(const uint8_t *addr) |
174 | { | 171 | { |
175 | const struct batadv_hard_iface *hard_iface; | 172 | const struct batadv_hard_iface *hard_iface; |
@@ -188,6 +185,42 @@ int batadv_is_my_mac(const uint8_t *addr) | |||
188 | return 0; | 185 | return 0; |
189 | } | 186 | } |
190 | 187 | ||
188 | /** | ||
189 | * batadv_seq_print_text_primary_if_get - called from debugfs table printing | ||
190 | * function that requires the primary interface | ||
191 | * @seq: debugfs table seq_file struct | ||
192 | * | ||
193 | * Returns primary interface if found or NULL otherwise. | ||
194 | */ | ||
195 | struct batadv_hard_iface * | ||
196 | batadv_seq_print_text_primary_if_get(struct seq_file *seq) | ||
197 | { | ||
198 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
199 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | ||
200 | struct batadv_hard_iface *primary_if; | ||
201 | |||
202 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
203 | |||
204 | if (!primary_if) { | ||
205 | seq_printf(seq, | ||
206 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
207 | net_dev->name); | ||
208 | goto out; | ||
209 | } | ||
210 | |||
211 | if (primary_if->if_status == BATADV_IF_ACTIVE) | ||
212 | goto out; | ||
213 | |||
214 | seq_printf(seq, | ||
215 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
216 | net_dev->name); | ||
217 | batadv_hardif_free_ref(primary_if); | ||
218 | primary_if = NULL; | ||
219 | |||
220 | out: | ||
221 | return primary_if; | ||
222 | } | ||
223 | |||
191 | static int batadv_recv_unhandled_packet(struct sk_buff *skb, | 224 | static int batadv_recv_unhandled_packet(struct sk_buff *skb, |
192 | struct batadv_hard_iface *recv_if) | 225 | struct batadv_hard_iface *recv_if) |
193 | { | 226 | { |
@@ -274,6 +307,8 @@ static void batadv_recv_handler_init(void) | |||
274 | 307 | ||
275 | /* batman icmp packet */ | 308 | /* batman icmp packet */ |
276 | batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; | 309 | batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; |
310 | /* unicast with 4 addresses packet */ | ||
311 | batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet; | ||
277 | /* unicast packet */ | 312 | /* unicast packet */ |
278 | batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet; | 313 | batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet; |
279 | /* fragmented unicast packet */ | 314 | /* fragmented unicast packet */ |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index d57b746219de..8f149bb66817 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -44,6 +44,7 @@ | |||
44 | #define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */ | 44 | #define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */ |
45 | #define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */ | 45 | #define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */ |
46 | #define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */ | 46 | #define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */ |
47 | #define BATADV_DAT_ENTRY_TIMEOUT (5*60000) /* 5 mins in milliseconds */ | ||
47 | /* sliding packet range of received originator messages in sequence numbers | 48 | /* sliding packet range of received originator messages in sequence numbers |
48 | * (should be a multiple of our word size) | 49 | * (should be a multiple of our word size) |
49 | */ | 50 | */ |
@@ -73,6 +74,11 @@ | |||
73 | 74 | ||
74 | #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 */ |
75 | 76 | ||
77 | /* msecs after which an ARP_REQUEST is sent in broadcast as fallback */ | ||
78 | #define ARP_REQ_DELAY 250 | ||
79 | /* numbers of originator to contact for any PUT/GET DHT operation */ | ||
80 | #define BATADV_DAT_CANDIDATES_NUM 3 | ||
81 | |||
76 | #define BATADV_VIS_INTERVAL 5000 /* 5 seconds */ | 82 | #define BATADV_VIS_INTERVAL 5000 /* 5 seconds */ |
77 | 83 | ||
78 | /* how much worse secondary interfaces may be to be considered as bonding | 84 | /* how much worse secondary interfaces may be to be considered as bonding |
@@ -89,6 +95,7 @@ | |||
89 | #define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ | 95 | #define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ |
90 | #define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) | 96 | #define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) |
91 | #define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) | 97 | #define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) |
98 | #define BATADV_BLA_WAIT_PERIODS 3 | ||
92 | 99 | ||
93 | #define BATADV_DUPLIST_SIZE 16 | 100 | #define BATADV_DUPLIST_SIZE 16 |
94 | #define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */ | 101 | #define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */ |
@@ -117,6 +124,9 @@ enum batadv_uev_type { | |||
117 | 124 | ||
118 | #define BATADV_GW_THRESHOLD 50 | 125 | #define BATADV_GW_THRESHOLD 50 |
119 | 126 | ||
127 | #define BATADV_DAT_CANDIDATE_NOT_FOUND 0 | ||
128 | #define BATADV_DAT_CANDIDATE_ORIG 1 | ||
129 | |||
120 | /* Debug Messages */ | 130 | /* Debug Messages */ |
121 | #ifdef pr_fmt | 131 | #ifdef pr_fmt |
122 | #undef pr_fmt | 132 | #undef pr_fmt |
@@ -150,9 +160,9 @@ extern struct workqueue_struct *batadv_event_workqueue; | |||
150 | 160 | ||
151 | int batadv_mesh_init(struct net_device *soft_iface); | 161 | int batadv_mesh_init(struct net_device *soft_iface); |
152 | void batadv_mesh_free(struct net_device *soft_iface); | 162 | void batadv_mesh_free(struct net_device *soft_iface); |
153 | void batadv_inc_module_count(void); | ||
154 | void batadv_dec_module_count(void); | ||
155 | int batadv_is_my_mac(const uint8_t *addr); | 163 | int batadv_is_my_mac(const uint8_t *addr); |
164 | struct batadv_hard_iface * | ||
165 | batadv_seq_print_text_primary_if_get(struct seq_file *seq); | ||
156 | int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | 166 | int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, |
157 | struct packet_type *ptype, | 167 | struct packet_type *ptype, |
158 | struct net_device *orig_dev); | 168 | struct net_device *orig_dev); |
@@ -165,13 +175,22 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops); | |||
165 | int batadv_algo_select(struct batadv_priv *bat_priv, char *name); | 175 | int batadv_algo_select(struct batadv_priv *bat_priv, char *name); |
166 | int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); | 176 | int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); |
167 | 177 | ||
168 | /* all messages related to routing / flooding / broadcasting / etc */ | 178 | /** |
179 | * enum batadv_dbg_level - available log levels | ||
180 | * @BATADV_DBG_BATMAN: OGM and TQ computations related messages | ||
181 | * @BATADV_DBG_ROUTES: route added / changed / deleted | ||
182 | * @BATADV_DBG_TT: translation table messages | ||
183 | * @BATADV_DBG_BLA: bridge loop avoidance messages | ||
184 | * @BATADV_DBG_DAT: ARP snooping and DAT related messages | ||
185 | * @BATADV_DBG_ALL: the union of all the above log levels | ||
186 | */ | ||
169 | enum batadv_dbg_level { | 187 | enum batadv_dbg_level { |
170 | BATADV_DBG_BATMAN = BIT(0), | 188 | BATADV_DBG_BATMAN = BIT(0), |
171 | BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */ | 189 | BATADV_DBG_ROUTES = BIT(1), |
172 | BATADV_DBG_TT = BIT(2), /* translation table operations */ | 190 | BATADV_DBG_TT = BIT(2), |
173 | BATADV_DBG_BLA = BIT(3), /* bridge loop avoidance */ | 191 | BATADV_DBG_BLA = BIT(3), |
174 | BATADV_DBG_ALL = 15, | 192 | BATADV_DBG_DAT = BIT(4), |
193 | BATADV_DBG_ALL = 31, | ||
175 | }; | 194 | }; |
176 | 195 | ||
177 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 196 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ac9bdf8f80a6..8c32cf1c2dec 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.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 "originator.h" | 22 | #include "originator.h" |
22 | #include "hash.h" | 23 | #include "hash.h" |
23 | #include "translation-table.h" | 24 | #include "translation-table.h" |
@@ -220,9 +221,9 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, | |||
220 | atomic_set(&orig_node->refcount, 2); | 221 | atomic_set(&orig_node->refcount, 2); |
221 | 222 | ||
222 | orig_node->tt_initialised = false; | 223 | orig_node->tt_initialised = false; |
223 | orig_node->tt_poss_change = false; | ||
224 | orig_node->bat_priv = bat_priv; | 224 | orig_node->bat_priv = bat_priv; |
225 | memcpy(orig_node->orig, addr, ETH_ALEN); | 225 | memcpy(orig_node->orig, addr, ETH_ALEN); |
226 | batadv_dat_init_orig_node_addr(orig_node); | ||
226 | orig_node->router = NULL; | 227 | orig_node->router = NULL; |
227 | orig_node->tt_crc = 0; | 228 | orig_node->tt_crc = 0; |
228 | atomic_set(&orig_node->last_ttvn, 0); | 229 | atomic_set(&orig_node->last_ttvn, 0); |
@@ -415,23 +416,10 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset) | |||
415 | int last_seen_msecs; | 416 | int last_seen_msecs; |
416 | unsigned long last_seen_jiffies; | 417 | unsigned long last_seen_jiffies; |
417 | uint32_t i; | 418 | uint32_t i; |
418 | int ret = 0; | ||
419 | 419 | ||
420 | primary_if = batadv_primary_if_get_selected(bat_priv); | 420 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
421 | 421 | if (!primary_if) | |
422 | if (!primary_if) { | ||
423 | ret = seq_printf(seq, | ||
424 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
425 | net_dev->name); | ||
426 | goto out; | ||
427 | } | ||
428 | |||
429 | if (primary_if->if_status != BATADV_IF_ACTIVE) { | ||
430 | ret = seq_printf(seq, | ||
431 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
432 | net_dev->name); | ||
433 | goto out; | 422 | goto out; |
434 | } | ||
435 | 423 | ||
436 | seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", | 424 | seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", |
437 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, | 425 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, |
@@ -485,7 +473,7 @@ next: | |||
485 | out: | 473 | out: |
486 | if (primary_if) | 474 | if (primary_if) |
487 | batadv_hardif_free_ref(primary_if); | 475 | batadv_hardif_free_ref(primary_if); |
488 | return ret; | 476 | return 0; |
489 | } | 477 | } |
490 | 478 | ||
491 | static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node, | 479 | static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node, |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 2d23a14c220e..df548ed196d3 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -23,14 +23,29 @@ | |||
23 | #define BATADV_ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */ | 23 | #define BATADV_ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */ |
24 | 24 | ||
25 | enum batadv_packettype { | 25 | enum batadv_packettype { |
26 | BATADV_IV_OGM = 0x01, | 26 | BATADV_IV_OGM = 0x01, |
27 | BATADV_ICMP = 0x02, | 27 | BATADV_ICMP = 0x02, |
28 | BATADV_UNICAST = 0x03, | 28 | BATADV_UNICAST = 0x03, |
29 | BATADV_BCAST = 0x04, | 29 | BATADV_BCAST = 0x04, |
30 | BATADV_VIS = 0x05, | 30 | BATADV_VIS = 0x05, |
31 | BATADV_UNICAST_FRAG = 0x06, | 31 | BATADV_UNICAST_FRAG = 0x06, |
32 | BATADV_TT_QUERY = 0x07, | 32 | BATADV_TT_QUERY = 0x07, |
33 | BATADV_ROAM_ADV = 0x08, | 33 | BATADV_ROAM_ADV = 0x08, |
34 | BATADV_UNICAST_4ADDR = 0x09, | ||
35 | }; | ||
36 | |||
37 | /** | ||
38 | * enum batadv_subtype - packet subtype for unicast4addr | ||
39 | * @BATADV_P_DATA: user payload | ||
40 | * @BATADV_P_DAT_DHT_GET: DHT request message | ||
41 | * @BATADV_P_DAT_DHT_PUT: DHT store message | ||
42 | * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT | ||
43 | */ | ||
44 | enum batadv_subtype { | ||
45 | BATADV_P_DATA = 0x01, | ||
46 | BATADV_P_DAT_DHT_GET = 0x02, | ||
47 | BATADV_P_DAT_DHT_PUT = 0x03, | ||
48 | BATADV_P_DAT_CACHE_REPLY = 0x04, | ||
34 | }; | 49 | }; |
35 | 50 | ||
36 | /* this file is included by batctl which needs these defines */ | 51 | /* this file is included by batctl which needs these defines */ |
@@ -106,13 +121,16 @@ struct batadv_bla_claim_dst { | |||
106 | uint8_t magic[3]; /* FF:43:05 */ | 121 | uint8_t magic[3]; /* FF:43:05 */ |
107 | uint8_t type; /* bla_claimframe */ | 122 | uint8_t type; /* bla_claimframe */ |
108 | __be16 group; /* group id */ | 123 | __be16 group; /* group id */ |
109 | } __packed; | 124 | }; |
110 | 125 | ||
111 | struct batadv_header { | 126 | struct batadv_header { |
112 | uint8_t packet_type; | 127 | uint8_t packet_type; |
113 | uint8_t version; /* batman version field */ | 128 | uint8_t version; /* batman version field */ |
114 | uint8_t ttl; | 129 | uint8_t ttl; |
115 | } __packed; | 130 | /* the parent struct has to add a byte after the header to make |
131 | * everything 4 bytes aligned again | ||
132 | */ | ||
133 | }; | ||
116 | 134 | ||
117 | struct batadv_ogm_packet { | 135 | struct batadv_ogm_packet { |
118 | struct batadv_header header; | 136 | struct batadv_header header; |
@@ -137,7 +155,7 @@ struct batadv_icmp_packet { | |||
137 | __be16 seqno; | 155 | __be16 seqno; |
138 | uint8_t uid; | 156 | uint8_t uid; |
139 | uint8_t reserved; | 157 | uint8_t reserved; |
140 | } __packed; | 158 | }; |
141 | 159 | ||
142 | #define BATADV_RR_LEN 16 | 160 | #define BATADV_RR_LEN 16 |
143 | 161 | ||
@@ -153,13 +171,32 @@ struct batadv_icmp_packet_rr { | |||
153 | uint8_t uid; | 171 | uint8_t uid; |
154 | uint8_t rr_cur; | 172 | uint8_t rr_cur; |
155 | uint8_t rr[BATADV_RR_LEN][ETH_ALEN]; | 173 | uint8_t rr[BATADV_RR_LEN][ETH_ALEN]; |
156 | } __packed; | 174 | }; |
157 | 175 | ||
158 | struct batadv_unicast_packet { | 176 | struct batadv_unicast_packet { |
159 | struct batadv_header header; | 177 | struct batadv_header header; |
160 | uint8_t ttvn; /* destination translation table version number */ | 178 | uint8_t ttvn; /* destination translation table version number */ |
161 | uint8_t dest[ETH_ALEN]; | 179 | uint8_t dest[ETH_ALEN]; |
162 | } __packed; | 180 | /* "4 bytes boundary + 2 bytes" long to make the payload after the |
181 | * following ethernet header again 4 bytes boundary aligned | ||
182 | */ | ||
183 | }; | ||
184 | |||
185 | /** | ||
186 | * struct batadv_unicast_4addr_packet - extended unicast packet | ||
187 | * @u: common unicast packet header | ||
188 | * @src: address of the source | ||
189 | * @subtype: packet subtype | ||
190 | */ | ||
191 | struct batadv_unicast_4addr_packet { | ||
192 | struct batadv_unicast_packet u; | ||
193 | uint8_t src[ETH_ALEN]; | ||
194 | uint8_t subtype; | ||
195 | uint8_t reserved; | ||
196 | /* "4 bytes boundary + 2 bytes" long to make the payload after the | ||
197 | * following ethernet header again 4 bytes boundary aligned | ||
198 | */ | ||
199 | }; | ||
163 | 200 | ||
164 | struct batadv_unicast_frag_packet { | 201 | struct batadv_unicast_frag_packet { |
165 | struct batadv_header header; | 202 | struct batadv_header header; |
@@ -176,6 +213,9 @@ struct batadv_bcast_packet { | |||
176 | uint8_t reserved; | 213 | uint8_t reserved; |
177 | __be32 seqno; | 214 | __be32 seqno; |
178 | uint8_t orig[ETH_ALEN]; | 215 | uint8_t orig[ETH_ALEN]; |
216 | /* "4 bytes boundary + 2 bytes" long to make the payload after the | ||
217 | * following ethernet header again 4 bytes boundary aligned | ||
218 | */ | ||
179 | } __packed; | 219 | } __packed; |
180 | 220 | ||
181 | struct batadv_vis_packet { | 221 | struct batadv_vis_packet { |
@@ -187,7 +227,7 @@ struct batadv_vis_packet { | |||
187 | uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */ | 227 | uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */ |
188 | uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */ | 228 | uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */ |
189 | uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */ | 229 | uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */ |
190 | } __packed; | 230 | }; |
191 | 231 | ||
192 | struct batadv_tt_query_packet { | 232 | struct batadv_tt_query_packet { |
193 | struct batadv_header header; | 233 | struct batadv_header header; |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 376b4cc6ca82..78d657264cbf 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); |
@@ -549,25 +550,18 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig, | |||
549 | if (tmp_neigh_node->if_incoming == recv_if) | 550 | if (tmp_neigh_node->if_incoming == recv_if) |
550 | continue; | 551 | continue; |
551 | 552 | ||
552 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | 553 | if (router && tmp_neigh_node->tq_avg <= router->tq_avg) |
553 | continue; | 554 | continue; |
554 | 555 | ||
555 | /* if we don't have a router yet | 556 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) |
556 | * or this one is better, choose it. | 557 | continue; |
557 | */ | ||
558 | if ((!router) || | ||
559 | (tmp_neigh_node->tq_avg > router->tq_avg)) { | ||
560 | /* decrement refcount of | ||
561 | * previously selected router | ||
562 | */ | ||
563 | if (router) | ||
564 | batadv_neigh_node_free_ref(router); | ||
565 | 558 | ||
566 | router = tmp_neigh_node; | 559 | /* decrement refcount of previously selected router */ |
567 | atomic_inc_not_zero(&router->refcount); | 560 | if (router) |
568 | } | 561 | batadv_neigh_node_free_ref(router); |
569 | 562 | ||
570 | batadv_neigh_node_free_ref(tmp_neigh_node); | 563 | /* we found a better router (or at least one valid router) */ |
564 | router = tmp_neigh_node; | ||
571 | } | 565 | } |
572 | 566 | ||
573 | /* use the first candidate if nothing was found. */ | 567 | /* use the first candidate if nothing was found. */ |
@@ -687,21 +681,8 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | |||
687 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 681 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
688 | struct batadv_roam_adv_packet *roam_adv_packet; | 682 | struct batadv_roam_adv_packet *roam_adv_packet; |
689 | struct batadv_orig_node *orig_node; | 683 | struct batadv_orig_node *orig_node; |
690 | struct ethhdr *ethhdr; | ||
691 | |||
692 | /* drop packet if it has not necessary minimum size */ | ||
693 | if (unlikely(!pskb_may_pull(skb, | ||
694 | sizeof(struct batadv_roam_adv_packet)))) | ||
695 | goto out; | ||
696 | |||
697 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
698 | |||
699 | /* packet with unicast indication but broadcast recipient */ | ||
700 | if (is_broadcast_ether_addr(ethhdr->h_dest)) | ||
701 | goto out; | ||
702 | 684 | ||
703 | /* packet with broadcast sender address */ | 685 | if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0) |
704 | if (is_broadcast_ether_addr(ethhdr->h_source)) | ||
705 | goto out; | 686 | goto out; |
706 | 687 | ||
707 | batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX); | 688 | batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX); |
@@ -730,12 +711,6 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | |||
730 | BATADV_TT_CLIENT_ROAM, | 711 | BATADV_TT_CLIENT_ROAM, |
731 | atomic_read(&orig_node->last_ttvn) + 1); | 712 | atomic_read(&orig_node->last_ttvn) + 1); |
732 | 713 | ||
733 | /* Roaming phase starts: I have new information but the ttvn has not | ||
734 | * been incremented yet. This flag will make me check all the incoming | ||
735 | * packets for the correct destination. | ||
736 | */ | ||
737 | bat_priv->tt.poss_change = true; | ||
738 | |||
739 | batadv_orig_node_free_ref(orig_node); | 714 | batadv_orig_node_free_ref(orig_node); |
740 | out: | 715 | out: |
741 | /* returning NET_RX_DROP will make the caller function kfree the skb */ | 716 | /* returning NET_RX_DROP will make the caller function kfree the skb */ |
@@ -918,80 +893,161 @@ out: | |||
918 | return ret; | 893 | return ret; |
919 | } | 894 | } |
920 | 895 | ||
896 | /** | ||
897 | * batadv_reroute_unicast_packet - update the unicast header for re-routing | ||
898 | * @bat_priv: the bat priv with all the soft interface information | ||
899 | * @unicast_packet: the unicast header to be updated | ||
900 | * @dst_addr: the payload destination | ||
901 | * | ||
902 | * Search the translation table for dst_addr and update the unicast header with | ||
903 | * the new corresponding information (originator address where the destination | ||
904 | * client currently is and its known TTVN) | ||
905 | * | ||
906 | * Returns true if the packet header has been updated, false otherwise | ||
907 | */ | ||
908 | static bool | ||
909 | batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, | ||
910 | struct batadv_unicast_packet *unicast_packet, | ||
911 | uint8_t *dst_addr) | ||
912 | { | ||
913 | struct batadv_orig_node *orig_node = NULL; | ||
914 | struct batadv_hard_iface *primary_if = NULL; | ||
915 | bool ret = false; | ||
916 | uint8_t *orig_addr, orig_ttvn; | ||
917 | |||
918 | if (batadv_is_my_client(bat_priv, dst_addr)) { | ||
919 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
920 | if (!primary_if) | ||
921 | goto out; | ||
922 | orig_addr = primary_if->net_dev->dev_addr; | ||
923 | orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | ||
924 | } else { | ||
925 | orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr); | ||
926 | if (!orig_node) | ||
927 | goto out; | ||
928 | |||
929 | if (batadv_compare_eth(orig_node->orig, unicast_packet->dest)) | ||
930 | goto out; | ||
931 | |||
932 | orig_addr = orig_node->orig; | ||
933 | orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
934 | } | ||
935 | |||
936 | /* update the packet header */ | ||
937 | memcpy(unicast_packet->dest, orig_addr, ETH_ALEN); | ||
938 | unicast_packet->ttvn = orig_ttvn; | ||
939 | |||
940 | ret = true; | ||
941 | out: | ||
942 | if (primary_if) | ||
943 | batadv_hardif_free_ref(primary_if); | ||
944 | if (orig_node) | ||
945 | batadv_orig_node_free_ref(orig_node); | ||
946 | |||
947 | return ret; | ||
948 | } | ||
949 | |||
921 | static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | 950 | static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, |
922 | struct sk_buff *skb) { | 951 | struct sk_buff *skb) { |
923 | uint8_t curr_ttvn; | 952 | uint8_t curr_ttvn, old_ttvn; |
924 | struct batadv_orig_node *orig_node; | 953 | struct batadv_orig_node *orig_node; |
925 | struct ethhdr *ethhdr; | 954 | struct ethhdr *ethhdr; |
926 | struct batadv_hard_iface *primary_if; | 955 | struct batadv_hard_iface *primary_if; |
927 | struct batadv_unicast_packet *unicast_packet; | 956 | struct batadv_unicast_packet *unicast_packet; |
928 | bool tt_poss_change; | ||
929 | int is_old_ttvn; | 957 | int is_old_ttvn; |
930 | 958 | ||
931 | /* I could need to modify it */ | 959 | /* check if there is enough data before accessing it */ |
932 | if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0) | 960 | if (pskb_may_pull(skb, sizeof(*unicast_packet) + ETH_HLEN) < 0) |
961 | return 0; | ||
962 | |||
963 | /* create a copy of the skb (in case of for re-routing) to modify it. */ | ||
964 | if (skb_cow(skb, sizeof(*unicast_packet)) < 0) | ||
933 | return 0; | 965 | return 0; |
934 | 966 | ||
935 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 967 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
968 | ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); | ||
936 | 969 | ||
937 | if (batadv_is_my_mac(unicast_packet->dest)) { | 970 | /* check if the destination client was served by this node and it is now |
938 | tt_poss_change = bat_priv->tt.poss_change; | 971 | * roaming. In this case, it means that the node has got a ROAM_ADV |
939 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | 972 | * message and that it knows the new destination in the mesh to re-route |
940 | } else { | 973 | * the packet to |
974 | */ | ||
975 | if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) { | ||
976 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | ||
977 | ethhdr->h_dest)) | ||
978 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, | ||
979 | bat_priv, | ||
980 | "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", | ||
981 | unicast_packet->dest, | ||
982 | ethhdr->h_dest); | ||
983 | /* at this point the mesh destination should have been | ||
984 | * substituted with the originator address found in the global | ||
985 | * table. If not, let the packet go untouched anyway because | ||
986 | * there is nothing the node can do | ||
987 | */ | ||
988 | return 1; | ||
989 | } | ||
990 | |||
991 | /* retrieve the TTVN known by this node for the packet destination. This | ||
992 | * value is used later to check if the node which sent (or re-routed | ||
993 | * last time) the packet had an updated information or not | ||
994 | */ | ||
995 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | ||
996 | if (!batadv_is_my_mac(unicast_packet->dest)) { | ||
941 | orig_node = batadv_orig_hash_find(bat_priv, | 997 | orig_node = batadv_orig_hash_find(bat_priv, |
942 | unicast_packet->dest); | 998 | unicast_packet->dest); |
943 | 999 | /* if it is not possible to find the orig_node representing the | |
1000 | * destination, the packet can immediately be dropped as it will | ||
1001 | * not be possible to deliver it | ||
1002 | */ | ||
944 | if (!orig_node) | 1003 | if (!orig_node) |
945 | return 0; | 1004 | return 0; |
946 | 1005 | ||
947 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | 1006 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
948 | tt_poss_change = orig_node->tt_poss_change; | ||
949 | batadv_orig_node_free_ref(orig_node); | 1007 | batadv_orig_node_free_ref(orig_node); |
950 | } | 1008 | } |
951 | 1009 | ||
952 | /* Check whether I have to reroute the packet */ | 1010 | /* check if the TTVN contained in the packet is fresher than what the |
1011 | * node knows | ||
1012 | */ | ||
953 | is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); | 1013 | is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); |
954 | if (is_old_ttvn || tt_poss_change) { | 1014 | if (!is_old_ttvn) |
955 | /* check if there is enough data before accessing it */ | 1015 | return 1; |
956 | if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) + | ||
957 | ETH_HLEN) < 0) | ||
958 | return 0; | ||
959 | 1016 | ||
960 | ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); | 1017 | old_ttvn = unicast_packet->ttvn; |
1018 | /* the packet was forged based on outdated network information. Its | ||
1019 | * destination can possibly be updated and forwarded towards the new | ||
1020 | * target host | ||
1021 | */ | ||
1022 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | ||
1023 | ethhdr->h_dest)) { | ||
1024 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, | ||
1025 | "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", | ||
1026 | unicast_packet->dest, ethhdr->h_dest, | ||
1027 | old_ttvn, curr_ttvn); | ||
1028 | return 1; | ||
1029 | } | ||
961 | 1030 | ||
962 | /* we don't have an updated route for this client, so we should | 1031 | /* the packet has not been re-routed: either the destination is |
963 | * not try to reroute the packet!! | 1032 | * currently served by this node or there is no destination at all and |
964 | */ | 1033 | * it is possible to drop the packet |
965 | if (batadv_tt_global_client_is_roaming(bat_priv, | 1034 | */ |
966 | ethhdr->h_dest)) | 1035 | if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) |
967 | return 1; | 1036 | return 0; |
968 | 1037 | ||
969 | orig_node = batadv_transtable_search(bat_priv, NULL, | 1038 | /* update the header in order to let the packet be delivered to this |
970 | ethhdr->h_dest); | 1039 | * node's soft interface |
971 | 1040 | */ | |
972 | if (!orig_node) { | 1041 | primary_if = batadv_primary_if_get_selected(bat_priv); |
973 | if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) | 1042 | if (!primary_if) |
974 | return 0; | 1043 | return 0; |
975 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
976 | if (!primary_if) | ||
977 | return 0; | ||
978 | memcpy(unicast_packet->dest, | ||
979 | primary_if->net_dev->dev_addr, ETH_ALEN); | ||
980 | batadv_hardif_free_ref(primary_if); | ||
981 | } else { | ||
982 | memcpy(unicast_packet->dest, orig_node->orig, | ||
983 | ETH_ALEN); | ||
984 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
985 | batadv_orig_node_free_ref(orig_node); | ||
986 | } | ||
987 | 1044 | ||
988 | batadv_dbg(BATADV_DBG_ROUTES, bat_priv, | 1045 | memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); |
989 | "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n", | 1046 | |
990 | unicast_packet->ttvn, curr_ttvn, ethhdr->h_dest, | 1047 | batadv_hardif_free_ref(primary_if); |
991 | unicast_packet->dest); | 1048 | |
1049 | unicast_packet->ttvn = curr_ttvn; | ||
992 | 1050 | ||
993 | unicast_packet->ttvn = curr_ttvn; | ||
994 | } | ||
995 | return 1; | 1051 | return 1; |
996 | } | 1052 | } |
997 | 1053 | ||
@@ -1000,7 +1056,19 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1000 | { | 1056 | { |
1001 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 1057 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
1002 | struct batadv_unicast_packet *unicast_packet; | 1058 | struct batadv_unicast_packet *unicast_packet; |
1059 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; | ||
1060 | uint8_t *orig_addr; | ||
1061 | struct batadv_orig_node *orig_node = NULL; | ||
1003 | int hdr_size = sizeof(*unicast_packet); | 1062 | int hdr_size = sizeof(*unicast_packet); |
1063 | bool is4addr; | ||
1064 | |||
1065 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | ||
1066 | unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; | ||
1067 | |||
1068 | is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR; | ||
1069 | /* the caller function should have already pulled 2 bytes */ | ||
1070 | if (is4addr) | ||
1071 | hdr_size = sizeof(*unicast_4addr_packet); | ||
1004 | 1072 | ||
1005 | if (batadv_check_unicast_packet(skb, hdr_size) < 0) | 1073 | if (batadv_check_unicast_packet(skb, hdr_size) < 0) |
1006 | return NET_RX_DROP; | 1074 | return NET_RX_DROP; |
@@ -1008,12 +1076,28 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1008 | if (!batadv_check_unicast_ttvn(bat_priv, skb)) | 1076 | if (!batadv_check_unicast_ttvn(bat_priv, skb)) |
1009 | return NET_RX_DROP; | 1077 | return NET_RX_DROP; |
1010 | 1078 | ||
1011 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | ||
1012 | |||
1013 | /* packet for me */ | 1079 | /* packet for me */ |
1014 | if (batadv_is_my_mac(unicast_packet->dest)) { | 1080 | if (batadv_is_my_mac(unicast_packet->dest)) { |
1081 | if (is4addr) { | ||
1082 | batadv_dat_inc_counter(bat_priv, | ||
1083 | unicast_4addr_packet->subtype); | ||
1084 | orig_addr = unicast_4addr_packet->src; | ||
1085 | orig_node = batadv_orig_hash_find(bat_priv, orig_addr); | ||
1086 | } | ||
1087 | |||
1088 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, | ||
1089 | hdr_size)) | ||
1090 | goto rx_success; | ||
1091 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, | ||
1092 | hdr_size)) | ||
1093 | goto rx_success; | ||
1094 | |||
1015 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, | 1095 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1016 | NULL); | 1096 | orig_node); |
1097 | |||
1098 | rx_success: | ||
1099 | if (orig_node) | ||
1100 | batadv_orig_node_free_ref(orig_node); | ||
1017 | 1101 | ||
1018 | return NET_RX_SUCCESS; | 1102 | return NET_RX_SUCCESS; |
1019 | } | 1103 | } |
@@ -1050,8 +1134,17 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb, | |||
1050 | if (!new_skb) | 1134 | if (!new_skb) |
1051 | return NET_RX_SUCCESS; | 1135 | return NET_RX_SUCCESS; |
1052 | 1136 | ||
1137 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb, | ||
1138 | hdr_size)) | ||
1139 | goto rx_success; | ||
1140 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb, | ||
1141 | hdr_size)) | ||
1142 | goto rx_success; | ||
1143 | |||
1053 | batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, | 1144 | batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, |
1054 | sizeof(struct batadv_unicast_packet), NULL); | 1145 | sizeof(struct batadv_unicast_packet), NULL); |
1146 | |||
1147 | rx_success: | ||
1055 | return NET_RX_SUCCESS; | 1148 | return NET_RX_SUCCESS; |
1056 | } | 1149 | } |
1057 | 1150 | ||
@@ -1143,9 +1236,16 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, | |||
1143 | if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) | 1236 | if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) |
1144 | goto out; | 1237 | goto out; |
1145 | 1238 | ||
1239 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size)) | ||
1240 | goto rx_success; | ||
1241 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) | ||
1242 | goto rx_success; | ||
1243 | |||
1146 | /* broadcast for me */ | 1244 | /* broadcast for me */ |
1147 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, | 1245 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1148 | orig_node); | 1246 | orig_node); |
1247 | |||
1248 | rx_success: | ||
1149 | ret = NET_RX_SUCCESS; | 1249 | ret = NET_RX_SUCCESS; |
1150 | goto out; | 1250 | goto out; |
1151 | 1251 | ||
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 ce0684a1fc83..54800c783f96 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" |
@@ -146,13 +147,16 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
146 | struct batadv_bcast_packet *bcast_packet; | 147 | struct batadv_bcast_packet *bcast_packet; |
147 | struct vlan_ethhdr *vhdr; | 148 | struct vlan_ethhdr *vhdr; |
148 | __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN); | 149 | __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN); |
149 | static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00, | 150 | static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, |
150 | 0x00}; | 151 | 0x00, 0x00}; |
152 | static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00, | ||
153 | 0x00, 0x00}; | ||
151 | unsigned int header_len = 0; | 154 | unsigned int header_len = 0; |
152 | int data_len = skb->len, ret; | 155 | int data_len = skb->len, ret; |
153 | short vid __maybe_unused = -1; | 156 | short vid __maybe_unused = -1; |
154 | bool do_bcast = false; | 157 | bool do_bcast = false; |
155 | uint32_t seqno; | 158 | uint32_t seqno; |
159 | unsigned long brd_delay = 1; | ||
156 | 160 | ||
157 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 161 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
158 | goto dropped; | 162 | goto dropped; |
@@ -180,10 +184,16 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
180 | 184 | ||
181 | /* don't accept stp packets. STP does not help in meshes. | 185 | /* don't accept stp packets. STP does not help in meshes. |
182 | * better use the bridge loop avoidance ... | 186 | * better use the bridge loop avoidance ... |
187 | * | ||
188 | * The same goes for ECTP sent at least by some Cisco Switches, | ||
189 | * it might confuse the mesh when used with bridge loop avoidance. | ||
183 | */ | 190 | */ |
184 | if (batadv_compare_eth(ethhdr->h_dest, stp_addr)) | 191 | if (batadv_compare_eth(ethhdr->h_dest, stp_addr)) |
185 | goto dropped; | 192 | goto dropped; |
186 | 193 | ||
194 | if (batadv_compare_eth(ethhdr->h_dest, ectp_addr)) | ||
195 | goto dropped; | ||
196 | |||
187 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 197 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
188 | do_bcast = true; | 198 | do_bcast = true; |
189 | 199 | ||
@@ -216,6 +226,13 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
216 | if (!primary_if) | 226 | if (!primary_if) |
217 | goto dropped; | 227 | goto dropped; |
218 | 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 | |||
219 | if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) | 236 | if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) |
220 | goto dropped; | 237 | goto dropped; |
221 | 238 | ||
@@ -237,7 +254,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
237 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); | 254 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); |
238 | bcast_packet->seqno = htonl(seqno); | 255 | bcast_packet->seqno = htonl(seqno); |
239 | 256 | ||
240 | batadv_add_bcast_packet_to_list(bat_priv, skb, 1); | 257 | batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay); |
241 | 258 | ||
242 | /* a copy is stored in the bcast list, therefore removing | 259 | /* a copy is stored in the bcast list, therefore removing |
243 | * the original skb. | 260 | * the original skb. |
@@ -252,7 +269,12 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
252 | goto dropped; | 269 | goto dropped; |
253 | } | 270 | } |
254 | 271 | ||
255 | ret = batadv_unicast_send_skb(skb, bat_priv); | 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 | |||
277 | ret = batadv_unicast_send_skb(bat_priv, skb); | ||
256 | if (ret != 0) | 278 | if (ret != 0) |
257 | goto dropped_freed; | 279 | goto dropped_freed; |
258 | } | 280 | } |
@@ -347,7 +369,51 @@ out: | |||
347 | return; | 369 | return; |
348 | } | 370 | } |
349 | 371 | ||
372 | /* batman-adv network devices have devices nesting below it and are a special | ||
373 | * "super class" of normal network devices; split their locks off into a | ||
374 | * separate class since they always nest. | ||
375 | */ | ||
376 | static struct lock_class_key batadv_netdev_xmit_lock_key; | ||
377 | static struct lock_class_key batadv_netdev_addr_lock_key; | ||
378 | |||
379 | /** | ||
380 | * batadv_set_lockdep_class_one - Set lockdep class for a single tx queue | ||
381 | * @dev: device which owns the tx queue | ||
382 | * @txq: tx queue to modify | ||
383 | * @_unused: always NULL | ||
384 | */ | ||
385 | static void batadv_set_lockdep_class_one(struct net_device *dev, | ||
386 | struct netdev_queue *txq, | ||
387 | void *_unused) | ||
388 | { | ||
389 | lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key); | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * batadv_set_lockdep_class - Set txq and addr_list lockdep class | ||
394 | * @dev: network device to modify | ||
395 | */ | ||
396 | static void batadv_set_lockdep_class(struct net_device *dev) | ||
397 | { | ||
398 | lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key); | ||
399 | netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL); | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * batadv_softif_init - Late stage initialization of soft interface | ||
404 | * @dev: registered network device to modify | ||
405 | * | ||
406 | * Returns error code on failures | ||
407 | */ | ||
408 | static int batadv_softif_init(struct net_device *dev) | ||
409 | { | ||
410 | batadv_set_lockdep_class(dev); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
350 | static const struct net_device_ops batadv_netdev_ops = { | 415 | static const struct net_device_ops batadv_netdev_ops = { |
416 | .ndo_init = batadv_softif_init, | ||
351 | .ndo_open = batadv_interface_open, | 417 | .ndo_open = batadv_interface_open, |
352 | .ndo_stop = batadv_interface_release, | 418 | .ndo_stop = batadv_interface_release, |
353 | .ndo_get_stats = batadv_interface_stats, | 419 | .ndo_get_stats = batadv_interface_stats, |
@@ -414,6 +480,9 @@ struct net_device *batadv_softif_create(const char *name) | |||
414 | atomic_set(&bat_priv->aggregated_ogms, 1); | 480 | atomic_set(&bat_priv->aggregated_ogms, 1); |
415 | atomic_set(&bat_priv->bonding, 0); | 481 | atomic_set(&bat_priv->bonding, 0); |
416 | atomic_set(&bat_priv->bridge_loop_avoidance, 0); | 482 | atomic_set(&bat_priv->bridge_loop_avoidance, 0); |
483 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
484 | atomic_set(&bat_priv->distributed_arp_table, 1); | ||
485 | #endif | ||
417 | atomic_set(&bat_priv->ap_isolation, 0); | 486 | atomic_set(&bat_priv->ap_isolation, 0); |
418 | atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE); | 487 | atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE); |
419 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); | 488 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); |
@@ -436,7 +505,6 @@ struct net_device *batadv_softif_create(const char *name) | |||
436 | #endif | 505 | #endif |
437 | bat_priv->tt.last_changeset = NULL; | 506 | bat_priv->tt.last_changeset = NULL; |
438 | bat_priv->tt.last_changeset_len = 0; | 507 | bat_priv->tt.last_changeset_len = 0; |
439 | bat_priv->tt.poss_change = false; | ||
440 | 508 | ||
441 | bat_priv->primary_if = NULL; | 509 | bat_priv->primary_if = NULL; |
442 | bat_priv->num_ifaces = 0; | 510 | bat_priv->num_ifaces = 0; |
@@ -556,6 +624,13 @@ static const struct { | |||
556 | { "tt_response_rx" }, | 624 | { "tt_response_rx" }, |
557 | { "tt_roam_adv_tx" }, | 625 | { "tt_roam_adv_tx" }, |
558 | { "tt_roam_adv_rx" }, | 626 | { "tt_roam_adv_rx" }, |
627 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
628 | { "dat_get_tx" }, | ||
629 | { "dat_get_rx" }, | ||
630 | { "dat_put_tx" }, | ||
631 | { "dat_put_rx" }, | ||
632 | { "dat_cached_reply_tx" }, | ||
633 | #endif | ||
559 | }; | 634 | }; |
560 | 635 | ||
561 | static void batadv_get_strings(struct net_device *dev, uint32_t stringset, | 636 | static void batadv_get_strings(struct net_device *dev, uint32_t stringset, |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 66518c75c217..84a55cb19b0b 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "main.h" | 20 | #include "main.h" |
21 | #include "sysfs.h" | 21 | #include "sysfs.h" |
22 | #include "translation-table.h" | 22 | #include "translation-table.h" |
23 | #include "distributed-arp-table.h" | ||
23 | #include "originator.h" | 24 | #include "originator.h" |
24 | #include "hard-interface.h" | 25 | #include "hard-interface.h" |
25 | #include "gateway_common.h" | 26 | #include "gateway_common.h" |
@@ -122,55 +123,6 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \ | |||
122 | batadv_store_##_name) | 123 | batadv_store_##_name) |
123 | 124 | ||
124 | 125 | ||
125 | #define BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func) \ | ||
126 | ssize_t batadv_store_##_name(struct kobject *kobj, \ | ||
127 | struct attribute *attr, char *buff, \ | ||
128 | size_t count) \ | ||
129 | { \ | ||
130 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ | ||
131 | struct batadv_hard_iface *hard_iface; \ | ||
132 | ssize_t length; \ | ||
133 | \ | ||
134 | hard_iface = batadv_hardif_get_by_netdev(net_dev); \ | ||
135 | if (!hard_iface) \ | ||
136 | return 0; \ | ||
137 | \ | ||
138 | length = __batadv_store_uint_attr(buff, count, _min, _max, \ | ||
139 | _post_func, attr, \ | ||
140 | &hard_iface->_name, net_dev); \ | ||
141 | \ | ||
142 | batadv_hardif_free_ref(hard_iface); \ | ||
143 | return length; \ | ||
144 | } | ||
145 | |||
146 | #define BATADV_ATTR_HIF_SHOW_UINT(_name) \ | ||
147 | ssize_t batadv_show_##_name(struct kobject *kobj, \ | ||
148 | struct attribute *attr, char *buff) \ | ||
149 | { \ | ||
150 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ | ||
151 | struct batadv_hard_iface *hard_iface; \ | ||
152 | ssize_t length; \ | ||
153 | \ | ||
154 | hard_iface = batadv_hardif_get_by_netdev(net_dev); \ | ||
155 | if (!hard_iface) \ | ||
156 | return 0; \ | ||
157 | \ | ||
158 | length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\ | ||
159 | \ | ||
160 | batadv_hardif_free_ref(hard_iface); \ | ||
161 | return length; \ | ||
162 | } | ||
163 | |||
164 | /* Use this, if you are going to set [name] in hard_iface to an | ||
165 | * unsigned integer value | ||
166 | */ | ||
167 | #define BATADV_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func) \ | ||
168 | static BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)\ | ||
169 | static BATADV_ATTR_HIF_SHOW_UINT(_name) \ | ||
170 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ | ||
171 | batadv_store_##_name) | ||
172 | |||
173 | |||
174 | static int batadv_store_bool_attr(char *buff, size_t count, | 126 | static int batadv_store_bool_attr(char *buff, size_t count, |
175 | struct net_device *net_dev, | 127 | struct net_device *net_dev, |
176 | const char *attr_name, atomic_t *attr) | 128 | const char *attr_name, atomic_t *attr) |
@@ -469,6 +421,9 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); | |||
469 | #ifdef CONFIG_BATMAN_ADV_BLA | 421 | #ifdef CONFIG_BATMAN_ADV_BLA |
470 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); | 422 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); |
471 | #endif | 423 | #endif |
424 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
425 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL); | ||
426 | #endif | ||
472 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); | 427 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); |
473 | BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); | 428 | BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); |
474 | static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode, | 429 | static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode, |
@@ -494,6 +449,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { | |||
494 | #ifdef CONFIG_BATMAN_ADV_BLA | 449 | #ifdef CONFIG_BATMAN_ADV_BLA |
495 | &batadv_attr_bridge_loop_avoidance, | 450 | &batadv_attr_bridge_loop_avoidance, |
496 | #endif | 451 | #endif |
452 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
453 | &batadv_attr_distributed_arp_table, | ||
454 | #endif | ||
497 | &batadv_attr_fragmentation, | 455 | &batadv_attr_fragmentation, |
498 | &batadv_attr_ap_isolation, | 456 | &batadv_attr_ap_isolation, |
499 | &batadv_attr_vis_mode, | 457 | &batadv_attr_vis_mode, |
@@ -730,7 +688,7 @@ int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, | |||
730 | enum batadv_uev_action action, const char *data) | 688 | enum batadv_uev_action action, const char *data) |
731 | { | 689 | { |
732 | int ret = -ENOMEM; | 690 | int ret = -ENOMEM; |
733 | struct batadv_hard_iface *primary_if = NULL; | 691 | struct batadv_hard_iface *primary_if; |
734 | struct kobject *bat_kobj; | 692 | struct kobject *bat_kobj; |
735 | char *uevent_env[4] = { NULL, NULL, NULL, NULL }; | 693 | char *uevent_env[4] = { NULL, NULL, NULL, NULL }; |
736 | 694 | ||
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index baae71585804..582f13405df9 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -238,92 +238,134 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv) | |||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | static void batadv_tt_global_free(struct batadv_priv *bat_priv, | ||
242 | struct batadv_tt_global_entry *tt_global, | ||
243 | const char *message) | ||
244 | { | ||
245 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
246 | "Deleting global tt entry %pM: %s\n", | ||
247 | tt_global->common.addr, message); | ||
248 | |||
249 | batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, | ||
250 | batadv_choose_orig, tt_global->common.addr); | ||
251 | batadv_tt_global_entry_free_ref(tt_global); | ||
252 | |||
253 | } | ||
254 | |||
241 | void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | 255 | void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, |
242 | int ifindex) | 256 | int ifindex) |
243 | { | 257 | { |
244 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 258 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
245 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 259 | struct batadv_tt_local_entry *tt_local; |
246 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 260 | struct batadv_tt_global_entry *tt_global; |
247 | struct hlist_head *head; | 261 | struct hlist_head *head; |
248 | struct hlist_node *node; | 262 | struct hlist_node *node; |
249 | struct batadv_tt_orig_list_entry *orig_entry; | 263 | struct batadv_tt_orig_list_entry *orig_entry; |
250 | int hash_added; | 264 | int hash_added; |
265 | bool roamed_back = false; | ||
251 | 266 | ||
252 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | 267 | tt_local = batadv_tt_local_hash_find(bat_priv, addr); |
268 | tt_global = batadv_tt_global_hash_find(bat_priv, addr); | ||
253 | 269 | ||
254 | if (tt_local_entry) { | 270 | if (tt_local) { |
255 | tt_local_entry->last_seen = jiffies; | 271 | tt_local->last_seen = jiffies; |
256 | /* possibly unset the BATADV_TT_CLIENT_PENDING flag */ | 272 | if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) { |
257 | tt_local_entry->common.flags &= ~BATADV_TT_CLIENT_PENDING; | 273 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
258 | goto out; | 274 | "Re-adding pending client %pM\n", addr); |
275 | /* whatever the reason why the PENDING flag was set, | ||
276 | * this is a client which was enqueued to be removed in | ||
277 | * this orig_interval. Since it popped up again, the | ||
278 | * flag can be reset like it was never enqueued | ||
279 | */ | ||
280 | tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING; | ||
281 | goto add_event; | ||
282 | } | ||
283 | |||
284 | if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) { | ||
285 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
286 | "Roaming client %pM came back to its original location\n", | ||
287 | addr); | ||
288 | /* the ROAM flag is set because this client roamed away | ||
289 | * and the node got a roaming_advertisement message. Now | ||
290 | * that the client popped up again at its original | ||
291 | * location such flag can be unset | ||
292 | */ | ||
293 | tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM; | ||
294 | roamed_back = true; | ||
295 | } | ||
296 | goto check_roaming; | ||
259 | } | 297 | } |
260 | 298 | ||
261 | tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC); | 299 | tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC); |
262 | if (!tt_local_entry) | 300 | if (!tt_local) |
263 | goto out; | 301 | goto out; |
264 | 302 | ||
265 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 303 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
266 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, | 304 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, |
267 | (uint8_t)atomic_read(&bat_priv->tt.vn)); | 305 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
268 | 306 | ||
269 | memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); | 307 | memcpy(tt_local->common.addr, addr, ETH_ALEN); |
270 | tt_local_entry->common.flags = BATADV_NO_FLAGS; | 308 | tt_local->common.flags = BATADV_NO_FLAGS; |
271 | if (batadv_is_wifi_iface(ifindex)) | 309 | if (batadv_is_wifi_iface(ifindex)) |
272 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; | 310 | tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; |
273 | atomic_set(&tt_local_entry->common.refcount, 2); | 311 | atomic_set(&tt_local->common.refcount, 2); |
274 | tt_local_entry->last_seen = jiffies; | 312 | tt_local->last_seen = jiffies; |
275 | tt_local_entry->common.added_at = tt_local_entry->last_seen; | 313 | tt_local->common.added_at = tt_local->last_seen; |
276 | 314 | ||
277 | /* the batman interface mac address should never be purged */ | 315 | /* the batman interface mac address should never be purged */ |
278 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) | 316 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) |
279 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NOPURGE; | 317 | tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; |
280 | 318 | ||
281 | /* The local entry has to be marked as NEW to avoid to send it in | 319 | /* The local entry has to be marked as NEW to avoid to send it in |
282 | * a full table response going out before the next ttvn increment | 320 | * a full table response going out before the next ttvn increment |
283 | * (consistency check) | 321 | * (consistency check) |
284 | */ | 322 | */ |
285 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW; | 323 | tt_local->common.flags |= BATADV_TT_CLIENT_NEW; |
286 | 324 | ||
287 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, | 325 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, |
288 | batadv_choose_orig, | 326 | batadv_choose_orig, &tt_local->common, |
289 | &tt_local_entry->common, | 327 | &tt_local->common.hash_entry); |
290 | &tt_local_entry->common.hash_entry); | ||
291 | 328 | ||
292 | if (unlikely(hash_added != 0)) { | 329 | if (unlikely(hash_added != 0)) { |
293 | /* remove the reference for the hash */ | 330 | /* remove the reference for the hash */ |
294 | batadv_tt_local_entry_free_ref(tt_local_entry); | 331 | batadv_tt_local_entry_free_ref(tt_local); |
295 | goto out; | 332 | goto out; |
296 | } | 333 | } |
297 | 334 | ||
298 | batadv_tt_local_event(bat_priv, addr, tt_local_entry->common.flags); | 335 | add_event: |
336 | batadv_tt_local_event(bat_priv, addr, tt_local->common.flags); | ||
299 | 337 | ||
300 | /* remove address from global hash if present */ | 338 | check_roaming: |
301 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); | 339 | /* Check whether it is a roaming, but don't do anything if the roaming |
302 | 340 | * process has already been handled | |
303 | /* Check whether it is a roaming! */ | 341 | */ |
304 | if (tt_global_entry) { | 342 | if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) { |
305 | /* These node are probably going to update their tt table */ | 343 | /* These node are probably going to update their tt table */ |
306 | head = &tt_global_entry->orig_list; | 344 | head = &tt_global->orig_list; |
307 | rcu_read_lock(); | 345 | rcu_read_lock(); |
308 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { | 346 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { |
309 | orig_entry->orig_node->tt_poss_change = true; | 347 | batadv_send_roam_adv(bat_priv, tt_global->common.addr, |
310 | |||
311 | batadv_send_roam_adv(bat_priv, | ||
312 | tt_global_entry->common.addr, | ||
313 | orig_entry->orig_node); | 348 | orig_entry->orig_node); |
314 | } | 349 | } |
315 | rcu_read_unlock(); | 350 | rcu_read_unlock(); |
316 | /* The global entry has to be marked as ROAMING and | 351 | if (roamed_back) { |
317 | * has to be kept for consistency purpose | 352 | batadv_tt_global_free(bat_priv, tt_global, |
318 | */ | 353 | "Roaming canceled"); |
319 | tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM; | 354 | tt_global = NULL; |
320 | tt_global_entry->roam_at = jiffies; | 355 | } else { |
356 | /* The global entry has to be marked as ROAMING and | ||
357 | * has to be kept for consistency purpose | ||
358 | */ | ||
359 | tt_global->common.flags |= BATADV_TT_CLIENT_ROAM; | ||
360 | tt_global->roam_at = jiffies; | ||
361 | } | ||
321 | } | 362 | } |
363 | |||
322 | out: | 364 | out: |
323 | if (tt_local_entry) | 365 | if (tt_local) |
324 | batadv_tt_local_entry_free_ref(tt_local_entry); | 366 | batadv_tt_local_entry_free_ref(tt_local); |
325 | if (tt_global_entry) | 367 | if (tt_global) |
326 | batadv_tt_global_entry_free_ref(tt_global_entry); | 368 | batadv_tt_global_entry_free_ref(tt_global); |
327 | } | 369 | } |
328 | 370 | ||
329 | static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, | 371 | static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, |
@@ -434,22 +476,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
434 | struct hlist_node *node; | 476 | struct hlist_node *node; |
435 | struct hlist_head *head; | 477 | struct hlist_head *head; |
436 | uint32_t i; | 478 | uint32_t i; |
437 | int ret = 0; | ||
438 | 479 | ||
439 | primary_if = batadv_primary_if_get_selected(bat_priv); | 480 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
440 | if (!primary_if) { | 481 | if (!primary_if) |
441 | ret = seq_printf(seq, | ||
442 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
443 | net_dev->name); | ||
444 | goto out; | ||
445 | } | ||
446 | |||
447 | if (primary_if->if_status != BATADV_IF_ACTIVE) { | ||
448 | ret = seq_printf(seq, | ||
449 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
450 | net_dev->name); | ||
451 | goto out; | 482 | goto out; |
452 | } | ||
453 | 483 | ||
454 | seq_printf(seq, | 484 | seq_printf(seq, |
455 | "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", | 485 | "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", |
@@ -479,7 +509,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
479 | out: | 509 | out: |
480 | if (primary_if) | 510 | if (primary_if) |
481 | batadv_hardif_free_ref(primary_if); | 511 | batadv_hardif_free_ref(primary_if); |
482 | return ret; | 512 | return 0; |
483 | } | 513 | } |
484 | 514 | ||
485 | static void | 515 | static void |
@@ -501,24 +531,57 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv, | |||
501 | tt_local_entry->common.addr, message); | 531 | tt_local_entry->common.addr, message); |
502 | } | 532 | } |
503 | 533 | ||
504 | void batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr, | 534 | /** |
505 | const char *message, bool roaming) | 535 | * batadv_tt_local_remove - logically remove an entry from the local table |
536 | * @bat_priv: the bat priv with all the soft interface information | ||
537 | * @addr: the MAC address of the client to remove | ||
538 | * @message: message to append to the log on deletion | ||
539 | * @roaming: true if the deletion is due to a roaming event | ||
540 | * | ||
541 | * Returns the flags assigned to the local entry before being deleted | ||
542 | */ | ||
543 | uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, | ||
544 | const uint8_t *addr, const char *message, | ||
545 | bool roaming) | ||
506 | { | 546 | { |
507 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 547 | struct batadv_tt_local_entry *tt_local_entry; |
508 | uint16_t flags; | 548 | uint16_t flags, curr_flags = BATADV_NO_FLAGS; |
509 | 549 | ||
510 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | 550 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); |
511 | if (!tt_local_entry) | 551 | if (!tt_local_entry) |
512 | goto out; | 552 | goto out; |
513 | 553 | ||
554 | curr_flags = tt_local_entry->common.flags; | ||
555 | |||
514 | flags = BATADV_TT_CLIENT_DEL; | 556 | flags = BATADV_TT_CLIENT_DEL; |
515 | if (roaming) | 557 | /* if this global entry addition is due to a roaming, the node has to |
558 | * mark the local entry as "roamed" in order to correctly reroute | ||
559 | * packets later | ||
560 | */ | ||
561 | if (roaming) { | ||
516 | flags |= BATADV_TT_CLIENT_ROAM; | 562 | flags |= BATADV_TT_CLIENT_ROAM; |
563 | /* mark the local client as ROAMed */ | ||
564 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM; | ||
565 | } | ||
566 | |||
567 | if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) { | ||
568 | batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, | ||
569 | message); | ||
570 | goto out; | ||
571 | } | ||
572 | /* if this client has been added right now, it is possible to | ||
573 | * immediately purge it | ||
574 | */ | ||
575 | batadv_tt_local_event(bat_priv, tt_local_entry->common.addr, | ||
576 | curr_flags | BATADV_TT_CLIENT_DEL); | ||
577 | hlist_del_rcu(&tt_local_entry->common.hash_entry); | ||
578 | batadv_tt_local_entry_free_ref(tt_local_entry); | ||
517 | 579 | ||
518 | batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); | ||
519 | out: | 580 | out: |
520 | if (tt_local_entry) | 581 | if (tt_local_entry) |
521 | batadv_tt_local_entry_free_ref(tt_local_entry); | 582 | batadv_tt_local_entry_free_ref(tt_local_entry); |
583 | |||
584 | return curr_flags; | ||
522 | } | 585 | } |
523 | 586 | ||
524 | static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv, | 587 | static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv, |
@@ -721,12 +784,23 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
721 | const unsigned char *tt_addr, uint8_t flags, | 784 | const unsigned char *tt_addr, uint8_t flags, |
722 | uint8_t ttvn) | 785 | uint8_t ttvn) |
723 | { | 786 | { |
724 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 787 | struct batadv_tt_global_entry *tt_global_entry; |
788 | struct batadv_tt_local_entry *tt_local_entry; | ||
725 | int ret = 0; | 789 | int ret = 0; |
726 | int hash_added; | 790 | int hash_added; |
727 | struct batadv_tt_common_entry *common; | 791 | struct batadv_tt_common_entry *common; |
792 | uint16_t local_flags; | ||
728 | 793 | ||
729 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); | 794 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); |
795 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr); | ||
796 | |||
797 | /* if the node already has a local client for this entry, it has to wait | ||
798 | * for a roaming advertisement instead of manually messing up the global | ||
799 | * table | ||
800 | */ | ||
801 | if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry && | ||
802 | !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) | ||
803 | goto out; | ||
730 | 804 | ||
731 | if (!tt_global_entry) { | 805 | if (!tt_global_entry) { |
732 | tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC); | 806 | tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC); |
@@ -738,6 +812,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
738 | 812 | ||
739 | common->flags = flags; | 813 | common->flags = flags; |
740 | tt_global_entry->roam_at = 0; | 814 | tt_global_entry->roam_at = 0; |
815 | /* node must store current time in case of roaming. This is | ||
816 | * needed to purge this entry out on timeout (if nobody claims | ||
817 | * it) | ||
818 | */ | ||
819 | if (flags & BATADV_TT_CLIENT_ROAM) | ||
820 | tt_global_entry->roam_at = jiffies; | ||
741 | atomic_set(&common->refcount, 2); | 821 | atomic_set(&common->refcount, 2); |
742 | common->added_at = jiffies; | 822 | common->added_at = jiffies; |
743 | 823 | ||
@@ -755,19 +835,31 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
755 | goto out_remove; | 835 | goto out_remove; |
756 | } | 836 | } |
757 | } else { | 837 | } else { |
838 | common = &tt_global_entry->common; | ||
758 | /* If there is already a global entry, we can use this one for | 839 | /* If there is already a global entry, we can use this one for |
759 | * our processing. | 840 | * our processing. |
760 | * But if we are trying to add a temporary client we can exit | 841 | * But if we are trying to add a temporary client then here are |
761 | * directly because the temporary information should never | 842 | * two options at this point: |
762 | * override any already known client state (whatever it is) | 843 | * 1) the global client is not a temporary client: the global |
844 | * client has to be left as it is, temporary information | ||
845 | * should never override any already known client state | ||
846 | * 2) the global client is a temporary client: purge the | ||
847 | * originator list and add the new one orig_entry | ||
763 | */ | 848 | */ |
764 | if (flags & BATADV_TT_CLIENT_TEMP) | 849 | if (flags & BATADV_TT_CLIENT_TEMP) { |
765 | goto out; | 850 | if (!(common->flags & BATADV_TT_CLIENT_TEMP)) |
851 | goto out; | ||
852 | if (batadv_tt_global_entry_has_orig(tt_global_entry, | ||
853 | orig_node)) | ||
854 | goto out_remove; | ||
855 | batadv_tt_global_del_orig_list(tt_global_entry); | ||
856 | goto add_orig_entry; | ||
857 | } | ||
766 | 858 | ||
767 | /* if the client was temporary added before receiving the first | 859 | /* if the client was temporary added before receiving the first |
768 | * OGM announcing it, we have to clear the TEMP flag | 860 | * OGM announcing it, we have to clear the TEMP flag |
769 | */ | 861 | */ |
770 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP; | 862 | common->flags &= ~BATADV_TT_CLIENT_TEMP; |
771 | 863 | ||
772 | /* the change can carry possible "attribute" flags like the | 864 | /* the change can carry possible "attribute" flags like the |
773 | * TT_CLIENT_WIFI, therefore they have to be copied in the | 865 | * TT_CLIENT_WIFI, therefore they have to be copied in the |
@@ -782,28 +874,40 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
782 | * We should first delete the old originator before adding the | 874 | * We should first delete the old originator before adding the |
783 | * new one. | 875 | * new one. |
784 | */ | 876 | */ |
785 | if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) { | 877 | if (common->flags & BATADV_TT_CLIENT_ROAM) { |
786 | batadv_tt_global_del_orig_list(tt_global_entry); | 878 | batadv_tt_global_del_orig_list(tt_global_entry); |
787 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; | 879 | common->flags &= ~BATADV_TT_CLIENT_ROAM; |
788 | tt_global_entry->roam_at = 0; | 880 | tt_global_entry->roam_at = 0; |
789 | } | 881 | } |
790 | } | 882 | } |
883 | add_orig_entry: | ||
791 | /* add the new orig_entry (if needed) or update it */ | 884 | /* add the new orig_entry (if needed) or update it */ |
792 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); | 885 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); |
793 | 886 | ||
794 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 887 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
795 | "Creating new global tt entry: %pM (via %pM)\n", | 888 | "Creating new global tt entry: %pM (via %pM)\n", |
796 | tt_global_entry->common.addr, orig_node->orig); | 889 | common->addr, orig_node->orig); |
890 | ret = 1; | ||
797 | 891 | ||
798 | out_remove: | 892 | out_remove: |
893 | |||
799 | /* remove address from local hash if present */ | 894 | /* remove address from local hash if present */ |
800 | batadv_tt_local_remove(bat_priv, tt_global_entry->common.addr, | 895 | local_flags = batadv_tt_local_remove(bat_priv, tt_addr, |
801 | "global tt received", | 896 | "global tt received", |
802 | flags & BATADV_TT_CLIENT_ROAM); | 897 | !!(flags & BATADV_TT_CLIENT_ROAM)); |
803 | ret = 1; | 898 | tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI; |
899 | |||
900 | if (!(flags & BATADV_TT_CLIENT_ROAM)) | ||
901 | /* this is a normal global add. Therefore the client is not in a | ||
902 | * roaming state anymore. | ||
903 | */ | ||
904 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; | ||
905 | |||
804 | out: | 906 | out: |
805 | if (tt_global_entry) | 907 | if (tt_global_entry) |
806 | batadv_tt_global_entry_free_ref(tt_global_entry); | 908 | batadv_tt_global_entry_free_ref(tt_global_entry); |
909 | if (tt_local_entry) | ||
910 | batadv_tt_local_entry_free_ref(tt_local_entry); | ||
807 | return ret; | 911 | return ret; |
808 | } | 912 | } |
809 | 913 | ||
@@ -848,22 +952,10 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
848 | struct hlist_node *node; | 952 | struct hlist_node *node; |
849 | struct hlist_head *head; | 953 | struct hlist_head *head; |
850 | uint32_t i; | 954 | uint32_t i; |
851 | int ret = 0; | ||
852 | 955 | ||
853 | primary_if = batadv_primary_if_get_selected(bat_priv); | 956 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
854 | if (!primary_if) { | 957 | if (!primary_if) |
855 | ret = seq_printf(seq, | ||
856 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
857 | net_dev->name); | ||
858 | goto out; | 958 | goto out; |
859 | } | ||
860 | |||
861 | if (primary_if->if_status != BATADV_IF_ACTIVE) { | ||
862 | ret = seq_printf(seq, | ||
863 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
864 | net_dev->name); | ||
865 | goto out; | ||
866 | } | ||
867 | 959 | ||
868 | seq_printf(seq, | 960 | seq_printf(seq, |
869 | "Globally announced TT entries received via the mesh %s\n", | 961 | "Globally announced TT entries received via the mesh %s\n", |
@@ -887,7 +979,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
887 | out: | 979 | out: |
888 | if (primary_if) | 980 | if (primary_if) |
889 | batadv_hardif_free_ref(primary_if); | 981 | batadv_hardif_free_ref(primary_if); |
890 | return ret; | 982 | return 0; |
891 | } | 983 | } |
892 | 984 | ||
893 | /* deletes the orig list of a tt_global_entry */ | 985 | /* deletes the orig list of a tt_global_entry */ |
@@ -933,21 +1025,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, | |||
933 | spin_unlock_bh(&tt_global_entry->list_lock); | 1025 | spin_unlock_bh(&tt_global_entry->list_lock); |
934 | } | 1026 | } |
935 | 1027 | ||
936 | static void | ||
937 | batadv_tt_global_del_struct(struct batadv_priv *bat_priv, | ||
938 | struct batadv_tt_global_entry *tt_global_entry, | ||
939 | const char *message) | ||
940 | { | ||
941 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
942 | "Deleting global tt entry %pM: %s\n", | ||
943 | tt_global_entry->common.addr, message); | ||
944 | |||
945 | batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, | ||
946 | batadv_choose_orig, tt_global_entry->common.addr); | ||
947 | batadv_tt_global_entry_free_ref(tt_global_entry); | ||
948 | |||
949 | } | ||
950 | |||
951 | /* If the client is to be deleted, we check if it is the last origantor entry | 1028 | /* If the client is to be deleted, we check if it is the last origantor entry |
952 | * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the | 1029 | * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the |
953 | * timer, otherwise we simply remove the originator scheduled for deletion. | 1030 | * timer, otherwise we simply remove the originator scheduled for deletion. |
@@ -996,7 +1073,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
996 | const unsigned char *addr, | 1073 | const unsigned char *addr, |
997 | const char *message, bool roaming) | 1074 | const char *message, bool roaming) |
998 | { | 1075 | { |
999 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 1076 | struct batadv_tt_global_entry *tt_global_entry; |
1000 | struct batadv_tt_local_entry *local_entry = NULL; | 1077 | struct batadv_tt_local_entry *local_entry = NULL; |
1001 | 1078 | ||
1002 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); | 1079 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); |
@@ -1008,8 +1085,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
1008 | orig_node, message); | 1085 | orig_node, message); |
1009 | 1086 | ||
1010 | if (hlist_empty(&tt_global_entry->orig_list)) | 1087 | if (hlist_empty(&tt_global_entry->orig_list)) |
1011 | batadv_tt_global_del_struct(bat_priv, tt_global_entry, | 1088 | batadv_tt_global_free(bat_priv, tt_global_entry, |
1012 | message); | 1089 | message); |
1013 | 1090 | ||
1014 | goto out; | 1091 | goto out; |
1015 | } | 1092 | } |
@@ -1032,7 +1109,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
1032 | if (local_entry) { | 1109 | if (local_entry) { |
1033 | /* local entry exists, case 2: client roamed to us. */ | 1110 | /* local entry exists, case 2: client roamed to us. */ |
1034 | batadv_tt_global_del_orig_list(tt_global_entry); | 1111 | batadv_tt_global_del_orig_list(tt_global_entry); |
1035 | batadv_tt_global_del_struct(bat_priv, tt_global_entry, message); | 1112 | batadv_tt_global_free(bat_priv, tt_global_entry, message); |
1036 | } else | 1113 | } else |
1037 | /* no local entry exists, case 1: check for roaming */ | 1114 | /* no local entry exists, case 1: check for roaming */ |
1038 | batadv_tt_global_del_roaming(bat_priv, tt_global_entry, | 1115 | batadv_tt_global_del_roaming(bat_priv, tt_global_entry, |
@@ -1211,7 +1288,8 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, | |||
1211 | 1288 | ||
1212 | if (src && atomic_read(&bat_priv->ap_isolation)) { | 1289 | if (src && atomic_read(&bat_priv->ap_isolation)) { |
1213 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); | 1290 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); |
1214 | if (!tt_local_entry) | 1291 | if (!tt_local_entry || |
1292 | (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)) | ||
1215 | goto out; | 1293 | goto out; |
1216 | } | 1294 | } |
1217 | 1295 | ||
@@ -1477,11 +1555,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, | |||
1477 | tt_tot = tt_len / sizeof(struct batadv_tt_change); | 1555 | tt_tot = tt_len / sizeof(struct batadv_tt_change); |
1478 | 1556 | ||
1479 | len = tt_query_size + tt_len; | 1557 | len = tt_query_size + tt_len; |
1480 | skb = dev_alloc_skb(len + ETH_HLEN); | 1558 | skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); |
1481 | if (!skb) | 1559 | if (!skb) |
1482 | goto out; | 1560 | goto out; |
1483 | 1561 | ||
1484 | skb_reserve(skb, ETH_HLEN); | 1562 | skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
1485 | tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len); | 1563 | tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len); |
1486 | tt_response->ttvn = ttvn; | 1564 | tt_response->ttvn = ttvn; |
1487 | 1565 | ||
@@ -1543,11 +1621,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv, | |||
1543 | if (!tt_req_node) | 1621 | if (!tt_req_node) |
1544 | goto out; | 1622 | goto out; |
1545 | 1623 | ||
1546 | skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN); | 1624 | skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN); |
1547 | if (!skb) | 1625 | if (!skb) |
1548 | goto out; | 1626 | goto out; |
1549 | 1627 | ||
1550 | skb_reserve(skb, ETH_HLEN); | 1628 | skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
1551 | 1629 | ||
1552 | tt_req_len = sizeof(*tt_request); | 1630 | tt_req_len = sizeof(*tt_request); |
1553 | tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len); | 1631 | tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len); |
@@ -1598,7 +1676,7 @@ static bool | |||
1598 | batadv_send_other_tt_response(struct batadv_priv *bat_priv, | 1676 | batadv_send_other_tt_response(struct batadv_priv *bat_priv, |
1599 | struct batadv_tt_query_packet *tt_request) | 1677 | struct batadv_tt_query_packet *tt_request) |
1600 | { | 1678 | { |
1601 | struct batadv_orig_node *req_dst_orig_node = NULL; | 1679 | struct batadv_orig_node *req_dst_orig_node; |
1602 | struct batadv_orig_node *res_dst_orig_node = NULL; | 1680 | struct batadv_orig_node *res_dst_orig_node = NULL; |
1603 | struct batadv_neigh_node *neigh_node = NULL; | 1681 | struct batadv_neigh_node *neigh_node = NULL; |
1604 | struct batadv_hard_iface *primary_if = NULL; | 1682 | struct batadv_hard_iface *primary_if = NULL; |
@@ -1658,11 +1736,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, | |||
1658 | tt_tot = tt_len / sizeof(struct batadv_tt_change); | 1736 | tt_tot = tt_len / sizeof(struct batadv_tt_change); |
1659 | 1737 | ||
1660 | len = sizeof(*tt_response) + tt_len; | 1738 | len = sizeof(*tt_response) + tt_len; |
1661 | skb = dev_alloc_skb(len + ETH_HLEN); | 1739 | skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); |
1662 | if (!skb) | 1740 | if (!skb) |
1663 | goto unlock; | 1741 | goto unlock; |
1664 | 1742 | ||
1665 | skb_reserve(skb, ETH_HLEN); | 1743 | skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
1666 | packet_pos = skb_put(skb, len); | 1744 | packet_pos = skb_put(skb, len); |
1667 | tt_response = (struct batadv_tt_query_packet *)packet_pos; | 1745 | tt_response = (struct batadv_tt_query_packet *)packet_pos; |
1668 | tt_response->ttvn = req_ttvn; | 1746 | tt_response->ttvn = req_ttvn; |
@@ -1733,7 +1811,7 @@ static bool | |||
1733 | batadv_send_my_tt_response(struct batadv_priv *bat_priv, | 1811 | batadv_send_my_tt_response(struct batadv_priv *bat_priv, |
1734 | struct batadv_tt_query_packet *tt_request) | 1812 | struct batadv_tt_query_packet *tt_request) |
1735 | { | 1813 | { |
1736 | struct batadv_orig_node *orig_node = NULL; | 1814 | struct batadv_orig_node *orig_node; |
1737 | struct batadv_neigh_node *neigh_node = NULL; | 1815 | struct batadv_neigh_node *neigh_node = NULL; |
1738 | struct batadv_hard_iface *primary_if = NULL; | 1816 | struct batadv_hard_iface *primary_if = NULL; |
1739 | uint8_t my_ttvn, req_ttvn, ttvn; | 1817 | uint8_t my_ttvn, req_ttvn, ttvn; |
@@ -1785,11 +1863,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1785 | tt_tot = tt_len / sizeof(struct batadv_tt_change); | 1863 | tt_tot = tt_len / sizeof(struct batadv_tt_change); |
1786 | 1864 | ||
1787 | len = sizeof(*tt_response) + tt_len; | 1865 | len = sizeof(*tt_response) + tt_len; |
1788 | skb = dev_alloc_skb(len + ETH_HLEN); | 1866 | skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); |
1789 | if (!skb) | 1867 | if (!skb) |
1790 | goto unlock; | 1868 | goto unlock; |
1791 | 1869 | ||
1792 | skb_reserve(skb, ETH_HLEN); | 1870 | skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
1793 | packet_pos = skb_put(skb, len); | 1871 | packet_pos = skb_put(skb, len); |
1794 | tt_response = (struct batadv_tt_query_packet *)packet_pos; | 1872 | tt_response = (struct batadv_tt_query_packet *)packet_pos; |
1795 | tt_response->ttvn = req_ttvn; | 1873 | tt_response->ttvn = req_ttvn; |
@@ -1899,7 +1977,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, | |||
1899 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, | 1977 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, |
1900 | struct batadv_tt_query_packet *tt_response) | 1978 | struct batadv_tt_query_packet *tt_response) |
1901 | { | 1979 | { |
1902 | struct batadv_orig_node *orig_node = NULL; | 1980 | struct batadv_orig_node *orig_node; |
1903 | 1981 | ||
1904 | orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); | 1982 | orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); |
1905 | if (!orig_node) | 1983 | if (!orig_node) |
@@ -1941,7 +2019,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv, | |||
1941 | 2019 | ||
1942 | bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) | 2020 | bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) |
1943 | { | 2021 | { |
1944 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 2022 | struct batadv_tt_local_entry *tt_local_entry; |
1945 | bool ret = false; | 2023 | bool ret = false; |
1946 | 2024 | ||
1947 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | 2025 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); |
@@ -1950,7 +2028,8 @@ bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) | |||
1950 | /* Check if the client has been logically deleted (but is kept for | 2028 | /* Check if the client has been logically deleted (but is kept for |
1951 | * consistency purpose) | 2029 | * consistency purpose) |
1952 | */ | 2030 | */ |
1953 | if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) | 2031 | if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) || |
2032 | (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM)) | ||
1954 | goto out; | 2033 | goto out; |
1955 | ret = true; | 2034 | ret = true; |
1956 | out: | 2035 | out: |
@@ -2001,10 +2080,6 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv, | |||
2001 | 2080 | ||
2002 | /* Recalculate the CRC for this orig_node and store it */ | 2081 | /* Recalculate the CRC for this orig_node and store it */ |
2003 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); | 2082 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); |
2004 | /* Roaming phase is over: tables are in sync again. I can | ||
2005 | * unset the flag | ||
2006 | */ | ||
2007 | orig_node->tt_poss_change = false; | ||
2008 | out: | 2083 | out: |
2009 | if (orig_node) | 2084 | if (orig_node) |
2010 | batadv_orig_node_free_ref(orig_node); | 2085 | batadv_orig_node_free_ref(orig_node); |
@@ -2123,11 +2198,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, | |||
2123 | if (!batadv_tt_check_roam_count(bat_priv, client)) | 2198 | if (!batadv_tt_check_roam_count(bat_priv, client)) |
2124 | goto out; | 2199 | goto out; |
2125 | 2200 | ||
2126 | skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN); | 2201 | skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN); |
2127 | if (!skb) | 2202 | if (!skb) |
2128 | goto out; | 2203 | goto out; |
2129 | 2204 | ||
2130 | skb_reserve(skb, ETH_HLEN); | 2205 | skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
2131 | 2206 | ||
2132 | roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len); | 2207 | roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len); |
2133 | 2208 | ||
@@ -2295,7 +2370,6 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, | |||
2295 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 2370 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
2296 | "Local changes committed, updating to ttvn %u\n", | 2371 | "Local changes committed, updating to ttvn %u\n", |
2297 | (uint8_t)atomic_read(&bat_priv->tt.vn)); | 2372 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
2298 | bat_priv->tt.poss_change = false; | ||
2299 | 2373 | ||
2300 | /* reset the sending counter */ | 2374 | /* reset the sending counter */ |
2301 | atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); | 2375 | atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); |
@@ -2407,11 +2481,6 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv, | |||
2407 | */ | 2481 | */ |
2408 | if (orig_node->tt_crc != tt_crc) | 2482 | if (orig_node->tt_crc != tt_crc) |
2409 | goto request_table; | 2483 | goto request_table; |
2410 | |||
2411 | /* Roaming phase is over: tables are in sync again. I can | ||
2412 | * unset the flag | ||
2413 | */ | ||
2414 | orig_node->tt_poss_change = false; | ||
2415 | } else { | 2484 | } else { |
2416 | /* if we missed more than one change or our tables are not | 2485 | /* if we missed more than one change or our tables are not |
2417 | * in sync anymore -> request fresh tt data | 2486 | * in sync anymore -> request fresh tt data |
@@ -2444,12 +2513,38 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | |||
2444 | if (!tt_global_entry) | 2513 | if (!tt_global_entry) |
2445 | goto out; | 2514 | goto out; |
2446 | 2515 | ||
2447 | ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM; | 2516 | ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM); |
2448 | batadv_tt_global_entry_free_ref(tt_global_entry); | 2517 | batadv_tt_global_entry_free_ref(tt_global_entry); |
2449 | out: | 2518 | out: |
2450 | return ret; | 2519 | return ret; |
2451 | } | 2520 | } |
2452 | 2521 | ||
2522 | /** | ||
2523 | * batadv_tt_local_client_is_roaming - tells whether the client is roaming | ||
2524 | * @bat_priv: the bat priv with all the soft interface information | ||
2525 | * @addr: the MAC address of the local client to query | ||
2526 | * | ||
2527 | * Returns true if the local client is known to be roaming (it is not served by | ||
2528 | * this node anymore) or not. If yes, the client is still present in the table | ||
2529 | * to keep the latter consistent with the node TTVN | ||
2530 | */ | ||
2531 | bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | ||
2532 | uint8_t *addr) | ||
2533 | { | ||
2534 | struct batadv_tt_local_entry *tt_local_entry; | ||
2535 | bool ret = false; | ||
2536 | |||
2537 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | ||
2538 | if (!tt_local_entry) | ||
2539 | goto out; | ||
2540 | |||
2541 | ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM; | ||
2542 | batadv_tt_local_entry_free_ref(tt_local_entry); | ||
2543 | out: | ||
2544 | return ret; | ||
2545 | |||
2546 | } | ||
2547 | |||
2453 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, | 2548 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, |
2454 | struct batadv_orig_node *orig_node, | 2549 | struct batadv_orig_node *orig_node, |
2455 | const unsigned char *addr) | 2550 | const unsigned char *addr) |
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index 811fffd4760c..46d4451a59ee 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
@@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num); | |||
24 | int batadv_tt_init(struct batadv_priv *bat_priv); | 24 | int batadv_tt_init(struct batadv_priv *bat_priv); |
25 | void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | 25 | void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, |
26 | int ifindex); | 26 | int ifindex); |
27 | void batadv_tt_local_remove(struct batadv_priv *bat_priv, | 27 | uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, |
28 | const uint8_t *addr, const char *message, | 28 | const uint8_t *addr, const char *message, |
29 | bool roaming); | 29 | bool roaming); |
30 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); | 30 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); |
31 | void batadv_tt_global_add_orig(struct batadv_priv *bat_priv, | 31 | void batadv_tt_global_add_orig(struct batadv_priv *bat_priv, |
32 | struct batadv_orig_node *orig_node, | 32 | struct batadv_orig_node *orig_node, |
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv, | |||
59 | int packet_min_len); | 59 | int packet_min_len); |
60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | 60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, |
61 | uint8_t *addr); | 61 | uint8_t *addr); |
62 | bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | ||
63 | uint8_t *addr); | ||
62 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, | 64 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, |
63 | struct batadv_orig_node *orig_node, | 65 | struct batadv_orig_node *orig_node, |
64 | const unsigned char *addr); | 66 | const unsigned char *addr); |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index ac1e07a80454..7b3d0d7ef06a 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -28,20 +28,41 @@ | |||
28 | (ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \ | 28 | (ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \ |
29 | sizeof(struct batadv_bcast_packet))) | 29 | sizeof(struct batadv_bcast_packet))) |
30 | 30 | ||
31 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
32 | |||
33 | /* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed, | ||
34 | * BATADV_DAT_ADDR_MAX is changed as well. | ||
35 | * | ||
36 | * *Please be careful: batadv_dat_addr_t must be UNSIGNED* | ||
37 | */ | ||
38 | #define batadv_dat_addr_t uint16_t | ||
39 | |||
40 | #endif /* CONFIG_BATMAN_ADV_DAT */ | ||
41 | |||
42 | /** | ||
43 | * struct batadv_hard_iface_bat_iv - per hard interface B.A.T.M.A.N. IV data | ||
44 | * @ogm_buff: buffer holding the OGM packet | ||
45 | * @ogm_buff_len: length of the OGM packet buffer | ||
46 | * @ogm_seqno: OGM sequence number - used to identify each OGM | ||
47 | */ | ||
48 | struct batadv_hard_iface_bat_iv { | ||
49 | unsigned char *ogm_buff; | ||
50 | int ogm_buff_len; | ||
51 | atomic_t ogm_seqno; | ||
52 | }; | ||
53 | |||
31 | struct batadv_hard_iface { | 54 | struct batadv_hard_iface { |
32 | struct list_head list; | 55 | struct list_head list; |
33 | int16_t if_num; | 56 | int16_t if_num; |
34 | char if_status; | 57 | char if_status; |
35 | struct net_device *net_dev; | 58 | struct net_device *net_dev; |
36 | atomic_t seqno; | ||
37 | atomic_t frag_seqno; | 59 | atomic_t frag_seqno; |
38 | unsigned char *packet_buff; | ||
39 | int packet_len; | ||
40 | struct kobject *hardif_obj; | 60 | struct kobject *hardif_obj; |
41 | atomic_t refcount; | 61 | atomic_t refcount; |
42 | struct packet_type batman_adv_ptype; | 62 | struct packet_type batman_adv_ptype; |
43 | struct net_device *soft_iface; | 63 | struct net_device *soft_iface; |
44 | struct rcu_head rcu; | 64 | struct rcu_head rcu; |
65 | struct batadv_hard_iface_bat_iv bat_iv; | ||
45 | }; | 66 | }; |
46 | 67 | ||
47 | /** | 68 | /** |
@@ -63,6 +84,9 @@ struct batadv_orig_node { | |||
63 | uint8_t orig[ETH_ALEN]; | 84 | uint8_t orig[ETH_ALEN]; |
64 | uint8_t primary_addr[ETH_ALEN]; | 85 | uint8_t primary_addr[ETH_ALEN]; |
65 | struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ | 86 | struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ |
87 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
88 | batadv_dat_addr_t dat_addr; | ||
89 | #endif | ||
66 | unsigned long *bcast_own; | 90 | unsigned long *bcast_own; |
67 | uint8_t *bcast_own_sum; | 91 | uint8_t *bcast_own_sum; |
68 | unsigned long last_seen; | 92 | unsigned long last_seen; |
@@ -77,13 +101,6 @@ struct batadv_orig_node { | |||
77 | spinlock_t tt_buff_lock; /* protects tt_buff */ | 101 | spinlock_t tt_buff_lock; /* protects tt_buff */ |
78 | atomic_t tt_size; | 102 | atomic_t tt_size; |
79 | bool tt_initialised; | 103 | bool tt_initialised; |
80 | /* The tt_poss_change flag is used to detect an ongoing roaming phase. | ||
81 | * If true, then I sent a Roaming_adv to this orig_node and I have to | ||
82 | * inspect every packet directed to it to check whether it is still | ||
83 | * the true destination or not. This flag will be reset to false as | ||
84 | * soon as I receive a new TTVN from this orig_node | ||
85 | */ | ||
86 | bool tt_poss_change; | ||
87 | uint32_t last_real_seqno; | 104 | uint32_t last_real_seqno; |
88 | uint8_t last_ttl; | 105 | uint8_t last_ttl; |
89 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 106 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
@@ -162,6 +179,13 @@ enum batadv_counters { | |||
162 | BATADV_CNT_TT_RESPONSE_RX, | 179 | BATADV_CNT_TT_RESPONSE_RX, |
163 | BATADV_CNT_TT_ROAM_ADV_TX, | 180 | BATADV_CNT_TT_ROAM_ADV_TX, |
164 | BATADV_CNT_TT_ROAM_ADV_RX, | 181 | BATADV_CNT_TT_ROAM_ADV_RX, |
182 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
183 | BATADV_CNT_DAT_GET_TX, | ||
184 | BATADV_CNT_DAT_GET_RX, | ||
185 | BATADV_CNT_DAT_PUT_TX, | ||
186 | BATADV_CNT_DAT_PUT_RX, | ||
187 | BATADV_CNT_DAT_CACHED_REPLY_TX, | ||
188 | #endif | ||
165 | BATADV_CNT_NUM, | 189 | BATADV_CNT_NUM, |
166 | }; | 190 | }; |
167 | 191 | ||
@@ -181,7 +205,6 @@ struct batadv_priv_tt { | |||
181 | atomic_t vn; | 205 | atomic_t vn; |
182 | atomic_t ogm_append_cnt; | 206 | atomic_t ogm_append_cnt; |
183 | atomic_t local_changes; | 207 | atomic_t local_changes; |
184 | bool poss_change; | ||
185 | struct list_head changes_list; | 208 | struct list_head changes_list; |
186 | struct batadv_hashtable *local_hash; | 209 | struct batadv_hashtable *local_hash; |
187 | struct batadv_hashtable *global_hash; | 210 | struct batadv_hashtable *global_hash; |
@@ -228,6 +251,20 @@ struct batadv_priv_vis { | |||
228 | struct batadv_vis_info *my_info; | 251 | struct batadv_vis_info *my_info; |
229 | }; | 252 | }; |
230 | 253 | ||
254 | /** | ||
255 | * struct batadv_priv_dat - per mesh interface DAT private data | ||
256 | * @addr: node DAT address | ||
257 | * @hash: hashtable representing the local ARP cache | ||
258 | * @work: work queue callback item for cache purging | ||
259 | */ | ||
260 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
261 | struct batadv_priv_dat { | ||
262 | batadv_dat_addr_t addr; | ||
263 | struct batadv_hashtable *hash; | ||
264 | struct delayed_work work; | ||
265 | }; | ||
266 | #endif | ||
267 | |||
231 | struct batadv_priv { | 268 | struct batadv_priv { |
232 | atomic_t mesh_state; | 269 | atomic_t mesh_state; |
233 | struct net_device_stats stats; | 270 | struct net_device_stats stats; |
@@ -237,6 +274,9 @@ struct batadv_priv { | |||
237 | atomic_t fragmentation; /* boolean */ | 274 | atomic_t fragmentation; /* boolean */ |
238 | atomic_t ap_isolation; /* boolean */ | 275 | atomic_t ap_isolation; /* boolean */ |
239 | atomic_t bridge_loop_avoidance; /* boolean */ | 276 | atomic_t bridge_loop_avoidance; /* boolean */ |
277 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
278 | atomic_t distributed_arp_table; /* boolean */ | ||
279 | #endif | ||
240 | atomic_t vis_mode; /* VIS_TYPE_* */ | 280 | atomic_t vis_mode; /* VIS_TYPE_* */ |
241 | atomic_t gw_mode; /* GW_MODE_* */ | 281 | atomic_t gw_mode; /* GW_MODE_* */ |
242 | atomic_t gw_sel_class; /* uint */ | 282 | atomic_t gw_sel_class; /* uint */ |
@@ -255,7 +295,7 @@ struct batadv_priv { | |||
255 | struct hlist_head forw_bcast_list; | 295 | struct hlist_head forw_bcast_list; |
256 | struct batadv_hashtable *orig_hash; | 296 | struct batadv_hashtable *orig_hash; |
257 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ | 297 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ |
258 | spinlock_t forw_bcast_list_lock; /* protects */ | 298 | spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */ |
259 | struct delayed_work orig_work; | 299 | struct delayed_work orig_work; |
260 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ | 300 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ |
261 | struct batadv_algo_ops *bat_algo_ops; | 301 | struct batadv_algo_ops *bat_algo_ops; |
@@ -265,6 +305,9 @@ struct batadv_priv { | |||
265 | struct batadv_priv_gw gw; | 305 | struct batadv_priv_gw gw; |
266 | struct batadv_priv_tt tt; | 306 | struct batadv_priv_tt tt; |
267 | struct batadv_priv_vis vis; | 307 | struct batadv_priv_vis vis; |
308 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
309 | struct batadv_priv_dat dat; | ||
310 | #endif | ||
268 | }; | 311 | }; |
269 | 312 | ||
270 | struct batadv_socket_client { | 313 | struct batadv_socket_client { |
@@ -318,6 +361,7 @@ struct batadv_backbone_gw { | |||
318 | struct hlist_node hash_entry; | 361 | struct hlist_node hash_entry; |
319 | struct batadv_priv *bat_priv; | 362 | struct batadv_priv *bat_priv; |
320 | unsigned long lasttime; /* last time we heard of this backbone gw */ | 363 | unsigned long lasttime; /* last time we heard of this backbone gw */ |
364 | atomic_t wait_periods; | ||
321 | atomic_t request_sent; | 365 | atomic_t request_sent; |
322 | atomic_t refcount; | 366 | atomic_t refcount; |
323 | struct rcu_head rcu; | 367 | struct rcu_head rcu; |
@@ -437,4 +481,36 @@ struct batadv_algo_ops { | |||
437 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); | 481 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); |
438 | }; | 482 | }; |
439 | 483 | ||
484 | /** | ||
485 | * struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It | ||
486 | * is used to stored ARP entries needed for the global DAT cache | ||
487 | * @ip: the IPv4 corresponding to this DAT/ARP entry | ||
488 | * @mac_addr: the MAC address associated to the stored IPv4 | ||
489 | * @last_update: time in jiffies when this entry was refreshed last time | ||
490 | * @hash_entry: hlist node for batadv_priv_dat::hash | ||
491 | * @refcount: number of contexts the object is used | ||
492 | * @rcu: struct used for freeing in an RCU-safe manner | ||
493 | */ | ||
494 | struct batadv_dat_entry { | ||
495 | __be32 ip; | ||
496 | uint8_t mac_addr[ETH_ALEN]; | ||
497 | unsigned long last_update; | ||
498 | struct hlist_node hash_entry; | ||
499 | atomic_t refcount; | ||
500 | struct rcu_head rcu; | ||
501 | }; | ||
502 | |||
503 | /** | ||
504 | * struct batadv_dat_candidate - candidate destination for DAT operations | ||
505 | * @type: the type of the selected candidate. It can one of the following: | ||
506 | * - BATADV_DAT_CANDIDATE_NOT_FOUND | ||
507 | * - BATADV_DAT_CANDIDATE_ORIG | ||
508 | * @orig_node: if type is BATADV_DAT_CANDIDATE_ORIG this field points to the | ||
509 | * corresponding originator node structure | ||
510 | */ | ||
511 | struct batadv_dat_candidate { | ||
512 | int type; | ||
513 | struct batadv_orig_node *orig_node; | ||
514 | }; | ||
515 | |||
440 | #endif /* _NET_BATMAN_ADV_TYPES_H_ */ | 516 | #endif /* _NET_BATMAN_ADV_TYPES_H_ */ |
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index f39723281ca1..c9a1f6523c36 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c | |||
@@ -291,7 +291,111 @@ out: | |||
291 | return ret; | 291 | return ret; |
292 | } | 292 | } |
293 | 293 | ||
294 | int batadv_unicast_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv) | 294 | /** |
295 | * batadv_unicast_push_and_fill_skb - extends the buffer and initializes the | ||
296 | * common fields for unicast packets | ||
297 | * @skb: packet | ||
298 | * @hdr_size: amount of bytes to push at the beginning of the skb | ||
299 | * @orig_node: the destination node | ||
300 | * | ||
301 | * Returns false if the buffer extension was not possible or true otherwise | ||
302 | */ | ||
303 | static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size, | ||
304 | struct batadv_orig_node *orig_node) | ||
305 | { | ||
306 | struct batadv_unicast_packet *unicast_packet; | ||
307 | uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
308 | |||
309 | if (batadv_skb_head_push(skb, hdr_size) < 0) | ||
310 | return false; | ||
311 | |||
312 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | ||
313 | unicast_packet->header.version = BATADV_COMPAT_VERSION; | ||
314 | /* batman packet type: unicast */ | ||
315 | unicast_packet->header.packet_type = BATADV_UNICAST; | ||
316 | /* set unicast ttl */ | ||
317 | unicast_packet->header.ttl = BATADV_TTL; | ||
318 | /* copy the destination for faster routing */ | ||
319 | memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); | ||
320 | /* set the destination tt version number */ | ||
321 | unicast_packet->ttvn = ttvn; | ||
322 | |||
323 | return true; | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * batadv_unicast_prepare_skb - encapsulate an skb with a unicast header | ||
328 | * @skb: the skb containing the payload to encapsulate | ||
329 | * @orig_node: the destination node | ||
330 | * | ||
331 | * Returns false if the payload could not be encapsulated or true otherwise | ||
332 | */ | ||
333 | static bool batadv_unicast_prepare_skb(struct sk_buff *skb, | ||
334 | struct batadv_orig_node *orig_node) | ||
335 | { | ||
336 | size_t uni_size = sizeof(struct batadv_unicast_packet); | ||
337 | return batadv_unicast_push_and_fill_skb(skb, uni_size, orig_node); | ||
338 | } | ||
339 | |||
340 | /** | ||
341 | * batadv_unicast_4addr_prepare_skb - encapsulate an skb with a unicast4addr | ||
342 | * header | ||
343 | * @bat_priv: the bat priv with all the soft interface information | ||
344 | * @skb: the skb containing the payload to encapsulate | ||
345 | * @orig_node: the destination node | ||
346 | * @packet_subtype: the batman 4addr packet subtype to use | ||
347 | * | ||
348 | * Returns false if the payload could not be encapsulated or true otherwise | ||
349 | */ | ||
350 | bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv, | ||
351 | struct sk_buff *skb, | ||
352 | struct batadv_orig_node *orig, | ||
353 | int packet_subtype) | ||
354 | { | ||
355 | struct batadv_hard_iface *primary_if; | ||
356 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; | ||
357 | bool ret = false; | ||
358 | |||
359 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
360 | if (!primary_if) | ||
361 | goto out; | ||
362 | |||
363 | /* pull the header space and fill the unicast_packet substructure. | ||
364 | * We can do that because the first member of the unicast_4addr_packet | ||
365 | * is of type struct unicast_packet | ||
366 | */ | ||
367 | if (!batadv_unicast_push_and_fill_skb(skb, | ||
368 | sizeof(*unicast_4addr_packet), | ||
369 | orig)) | ||
370 | goto out; | ||
371 | |||
372 | unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; | ||
373 | unicast_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR; | ||
374 | memcpy(unicast_4addr_packet->src, primary_if->net_dev->dev_addr, | ||
375 | ETH_ALEN); | ||
376 | unicast_4addr_packet->subtype = packet_subtype; | ||
377 | unicast_4addr_packet->reserved = 0; | ||
378 | |||
379 | ret = true; | ||
380 | out: | ||
381 | if (primary_if) | ||
382 | batadv_hardif_free_ref(primary_if); | ||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * batadv_unicast_generic_send_skb - send an skb as unicast | ||
388 | * @bat_priv: the bat priv with all the soft interface information | ||
389 | * @skb: payload to send | ||
390 | * @packet_type: the batman unicast packet type to use | ||
391 | * @packet_subtype: the batman packet subtype. It is ignored if packet_type is | ||
392 | * not BATADV_UNICAT_4ADDR | ||
393 | * | ||
394 | * Returns 1 in case of error or 0 otherwise | ||
395 | */ | ||
396 | int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, | ||
397 | struct sk_buff *skb, int packet_type, | ||
398 | int packet_subtype) | ||
295 | { | 399 | { |
296 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 400 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
297 | struct batadv_unicast_packet *unicast_packet; | 401 | struct batadv_unicast_packet *unicast_packet; |
@@ -324,21 +428,23 @@ find_router: | |||
324 | if (!neigh_node) | 428 | if (!neigh_node) |
325 | goto out; | 429 | goto out; |
326 | 430 | ||
327 | if (batadv_skb_head_push(skb, sizeof(*unicast_packet)) < 0) | 431 | switch (packet_type) { |
432 | case BATADV_UNICAST: | ||
433 | batadv_unicast_prepare_skb(skb, orig_node); | ||
434 | break; | ||
435 | case BATADV_UNICAST_4ADDR: | ||
436 | batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node, | ||
437 | packet_subtype); | ||
438 | break; | ||
439 | default: | ||
440 | /* this function supports UNICAST and UNICAST_4ADDR only. It | ||
441 | * should never be invoked with any other packet type | ||
442 | */ | ||
328 | goto out; | 443 | goto out; |
444 | } | ||
329 | 445 | ||
330 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 446 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
331 | 447 | ||
332 | unicast_packet->header.version = BATADV_COMPAT_VERSION; | ||
333 | /* batman packet type: unicast */ | ||
334 | unicast_packet->header.packet_type = BATADV_UNICAST; | ||
335 | /* set unicast ttl */ | ||
336 | unicast_packet->header.ttl = BATADV_TTL; | ||
337 | /* copy the destination for faster routing */ | ||
338 | memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); | ||
339 | /* set the destination tt version number */ | ||
340 | unicast_packet->ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
341 | |||
342 | /* inform the destination node that we are still missing a correct route | 448 | /* inform the destination node that we are still missing a correct route |
343 | * for this client. The destination will receive this packet and will | 449 | * for this client. The destination will receive this packet and will |
344 | * try to reroute it because the ttvn contained in the header is less | 450 | * try to reroute it because the ttvn contained in the header is less |
@@ -348,7 +454,9 @@ find_router: | |||
348 | unicast_packet->ttvn = unicast_packet->ttvn - 1; | 454 | unicast_packet->ttvn = unicast_packet->ttvn - 1; |
349 | 455 | ||
350 | dev_mtu = neigh_node->if_incoming->net_dev->mtu; | 456 | dev_mtu = neigh_node->if_incoming->net_dev->mtu; |
351 | if (atomic_read(&bat_priv->fragmentation) && | 457 | /* fragmentation mechanism only works for UNICAST (now) */ |
458 | if (packet_type == BATADV_UNICAST && | ||
459 | atomic_read(&bat_priv->fragmentation) && | ||
352 | data_len + sizeof(*unicast_packet) > dev_mtu) { | 460 | data_len + sizeof(*unicast_packet) > dev_mtu) { |
353 | /* send frag skb decreases ttl */ | 461 | /* send frag skb decreases ttl */ |
354 | unicast_packet->header.ttl++; | 462 | unicast_packet->header.ttl++; |
@@ -360,7 +468,6 @@ find_router: | |||
360 | 468 | ||
361 | batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 469 | batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
362 | ret = 0; | 470 | ret = 0; |
363 | goto out; | ||
364 | 471 | ||
365 | out: | 472 | out: |
366 | if (neigh_node) | 473 | if (neigh_node) |
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h index 1c46e2eb1ef9..61abba58bd8f 100644 --- a/net/batman-adv/unicast.h +++ b/net/batman-adv/unicast.h | |||
@@ -29,10 +29,44 @@ int batadv_frag_reassemble_skb(struct sk_buff *skb, | |||
29 | struct batadv_priv *bat_priv, | 29 | struct batadv_priv *bat_priv, |
30 | struct sk_buff **new_skb); | 30 | struct sk_buff **new_skb); |
31 | void batadv_frag_list_free(struct list_head *head); | 31 | void batadv_frag_list_free(struct list_head *head); |
32 | int batadv_unicast_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv); | ||
33 | int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv, | 32 | int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv, |
34 | struct batadv_hard_iface *hard_iface, | 33 | struct batadv_hard_iface *hard_iface, |
35 | const uint8_t dstaddr[]); | 34 | const uint8_t dstaddr[]); |
35 | bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv, | ||
36 | struct sk_buff *skb, | ||
37 | struct batadv_orig_node *orig_node, | ||
38 | int packet_subtype); | ||
39 | int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, | ||
40 | struct sk_buff *skb, int packet_type, | ||
41 | int packet_subtype); | ||
42 | |||
43 | |||
44 | /** | ||
45 | * batadv_unicast_send_skb - send the skb encapsulated in a unicast packet | ||
46 | * @bat_priv: the bat priv with all the soft interface information | ||
47 | * @skb: the payload to send | ||
48 | */ | ||
49 | static inline int batadv_unicast_send_skb(struct batadv_priv *bat_priv, | ||
50 | struct sk_buff *skb) | ||
51 | { | ||
52 | return batadv_unicast_generic_send_skb(bat_priv, skb, BATADV_UNICAST, | ||
53 | 0); | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * batadv_unicast_send_skb - send the skb encapsulated in a unicast4addr packet | ||
58 | * @bat_priv: the bat priv with all the soft interface information | ||
59 | * @skb: the payload to send | ||
60 | * @packet_subtype: the batman 4addr packet subtype to use | ||
61 | */ | ||
62 | static inline int batadv_unicast_4addr_send_skb(struct batadv_priv *bat_priv, | ||
63 | struct sk_buff *skb, | ||
64 | int packet_subtype) | ||
65 | { | ||
66 | return batadv_unicast_generic_send_skb(bat_priv, skb, | ||
67 | BATADV_UNICAST_4ADDR, | ||
68 | packet_subtype); | ||
69 | } | ||
36 | 70 | ||
37 | static inline int batadv_frag_can_reassemble(const struct sk_buff *skb, int mtu) | 71 | static inline int batadv_frag_can_reassemble(const struct sk_buff *skb, int mtu) |
38 | { | 72 | { |
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index 5abd1454fb07..ad14a6c91d6a 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -396,12 +396,12 @@ batadv_add_packet(struct batadv_priv *bat_priv, | |||
396 | return NULL; | 396 | return NULL; |
397 | 397 | ||
398 | len = sizeof(*packet) + vis_info_len; | 398 | len = sizeof(*packet) + vis_info_len; |
399 | info->skb_packet = dev_alloc_skb(len + ETH_HLEN); | 399 | info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); |
400 | if (!info->skb_packet) { | 400 | if (!info->skb_packet) { |
401 | kfree(info); | 401 | kfree(info); |
402 | return NULL; | 402 | return NULL; |
403 | } | 403 | } |
404 | skb_reserve(info->skb_packet, ETH_HLEN); | 404 | skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN); |
405 | packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len); | 405 | packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len); |
406 | 406 | ||
407 | kref_init(&info->refcount); | 407 | kref_init(&info->refcount); |
@@ -873,12 +873,13 @@ int batadv_vis_init(struct batadv_priv *bat_priv) | |||
873 | if (!bat_priv->vis.my_info) | 873 | if (!bat_priv->vis.my_info) |
874 | goto err; | 874 | goto err; |
875 | 875 | ||
876 | len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN; | 876 | len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE; |
877 | len += ETH_HLEN + NET_IP_ALIGN; | ||
877 | bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len); | 878 | bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len); |
878 | if (!bat_priv->vis.my_info->skb_packet) | 879 | if (!bat_priv->vis.my_info->skb_packet) |
879 | goto free_info; | 880 | goto free_info; |
880 | 881 | ||
881 | skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN); | 882 | skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN); |
882 | tmp_skb = bat_priv->vis.my_info->skb_packet; | 883 | tmp_skb = bat_priv->vis.my_info->skb_packet; |
883 | packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet)); | 884 | packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet)); |
884 | 885 | ||