aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-05-11 17:57:52 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-11 17:57:52 -0400
commit16c788dee1934c2cc4e98692a5a63132d6e07d50 (patch)
treeebf3db929e39946d44377be7683156fed8f8bc3d
parent06a4c1c55dbe5d9f7a708e8f1a52fd2ac8e5874f (diff)
parent35c133a000d54b7e3fe81e8c8e4b8af5878ad6dd (diff)
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Included changes: * fix a little bug in the DHCP packet snooping introduced so far * minor fixes and cleanups * minor routing protocol API cleanups * add a new contributor name to translation-table.{c,h} * update copyright years in file headers * minor improvement for the routing algorithm
-rw-r--r--net/batman-adv/bat_debugfs.c4
-rw-r--r--net/batman-adv/bat_iv_ogm.c176
-rw-r--r--net/batman-adv/bat_sysfs.c100
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c2
-rw-r--r--net/batman-adv/bridge_loop_avoidance.h2
-rw-r--r--net/batman-adv/gateway_client.c6
-rw-r--r--net/batman-adv/hard-interface.c117
-rw-r--r--net/batman-adv/main.c124
-rw-r--r--net/batman-adv/main.h6
-rw-r--r--net/batman-adv/originator.c51
-rw-r--r--net/batman-adv/originator.h7
-rw-r--r--net/batman-adv/packet.h1
-rw-r--r--net/batman-adv/routing.c22
-rw-r--r--net/batman-adv/routing.h4
-rw-r--r--net/batman-adv/send.c2
-rw-r--r--net/batman-adv/translation-table.c2
-rw-r--r--net/batman-adv/translation-table.h2
-rw-r--r--net/batman-adv/types.h17
18 files changed, 380 insertions, 265 deletions
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c
index 916380c73ab7..3b588f86d770 100644
--- a/net/batman-adv/bat_debugfs.c
+++ b/net/batman-adv/bat_debugfs.c
@@ -83,8 +83,8 @@ int debug_log(struct bat_priv *bat_priv, const char *fmt, ...)
83 83
84 va_start(args, fmt); 84 va_start(args, fmt);
85 vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args); 85 vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
86 fdebug_log(bat_priv->debug_log, "[%10lu] %s", 86 fdebug_log(bat_priv->debug_log, "[%10u] %s",
87 (jiffies / HZ), tmp_log_buf); 87 jiffies_to_msecs(jiffies), tmp_log_buf);
88 va_end(args); 88 va_end(args);
89 89
90 return 0; 90 return 0;
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 8b2db2e76c7e..abd10c490fd9 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -30,6 +30,32 @@
30#include "send.h" 30#include "send.h"
31#include "bat_algo.h" 31#include "bat_algo.h"
32 32
33static struct neigh_node *bat_iv_ogm_neigh_new(struct hard_iface *hard_iface,
34 const uint8_t *neigh_addr,
35 struct orig_node *orig_node,
36 struct orig_node *orig_neigh,
37 uint32_t seqno)
38{
39 struct neigh_node *neigh_node;
40
41 neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, seqno);
42 if (!neigh_node)
43 goto out;
44
45 INIT_LIST_HEAD(&neigh_node->bonding_list);
46 spin_lock_init(&neigh_node->tq_lock);
47
48 neigh_node->orig_node = orig_neigh;
49 neigh_node->if_incoming = hard_iface;
50
51 spin_lock_bh(&orig_node->neigh_list_lock);
52 hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
53 spin_unlock_bh(&orig_node->neigh_list_lock);
54
55out:
56 return neigh_node;
57}
58
33static int bat_iv_ogm_iface_enable(struct hard_iface *hard_iface) 59static int bat_iv_ogm_iface_enable(struct hard_iface *hard_iface)
34{ 60{
35 struct batman_ogm_packet *batman_ogm_packet; 61 struct batman_ogm_packet *batman_ogm_packet;
@@ -67,24 +93,24 @@ static void bat_iv_ogm_iface_disable(struct hard_iface *hard_iface)
67 hard_iface->packet_buff = NULL; 93 hard_iface->packet_buff = NULL;
68} 94}
69 95
70static void bat_iv_ogm_primary_iface_set(struct hard_iface *hard_iface) 96static void bat_iv_ogm_iface_update_mac(struct hard_iface *hard_iface)
71{ 97{
72 struct batman_ogm_packet *batman_ogm_packet; 98 struct batman_ogm_packet *batman_ogm_packet;
73 99
74 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; 100 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
75 batman_ogm_packet->flags = PRIMARIES_FIRST_HOP; 101 memcpy(batman_ogm_packet->orig,
76 batman_ogm_packet->header.ttl = TTL; 102 hard_iface->net_dev->dev_addr, ETH_ALEN);
103 memcpy(batman_ogm_packet->prev_sender,
104 hard_iface->net_dev->dev_addr, ETH_ALEN);
77} 105}
78 106
79static void bat_iv_ogm_update_mac(struct hard_iface *hard_iface) 107static void bat_iv_ogm_primary_iface_set(struct hard_iface *hard_iface)
80{ 108{
81 struct batman_ogm_packet *batman_ogm_packet; 109 struct batman_ogm_packet *batman_ogm_packet;
82 110
83 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; 111 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
84 memcpy(batman_ogm_packet->orig, 112 batman_ogm_packet->flags = PRIMARIES_FIRST_HOP;
85 hard_iface->net_dev->dev_addr, ETH_ALEN); 113 batman_ogm_packet->header.ttl = TTL;
86 memcpy(batman_ogm_packet->prev_sender,
87 hard_iface->net_dev->dev_addr, ETH_ALEN);
88} 114}
89 115
90/* when do we schedule our own ogm to be sent */ 116/* when do we schedule our own ogm to be sent */
@@ -480,11 +506,11 @@ static void bat_iv_ogm_queue_add(struct bat_priv *bat_priv,
480static void bat_iv_ogm_forward(struct orig_node *orig_node, 506static void bat_iv_ogm_forward(struct orig_node *orig_node,
481 const struct ethhdr *ethhdr, 507 const struct ethhdr *ethhdr,
482 struct batman_ogm_packet *batman_ogm_packet, 508 struct batman_ogm_packet *batman_ogm_packet,
483 int directlink, struct hard_iface *if_incoming) 509 bool is_single_hop_neigh,
510 bool is_from_best_next_hop,
511 struct hard_iface *if_incoming)
484{ 512{
485 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 513 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
486 struct neigh_node *router;
487 uint8_t in_tq, in_ttl, tq_avg = 0;
488 uint8_t tt_num_changes; 514 uint8_t tt_num_changes;
489 515
490 if (batman_ogm_packet->header.ttl <= 1) { 516 if (batman_ogm_packet->header.ttl <= 1) {
@@ -492,48 +518,37 @@ static void bat_iv_ogm_forward(struct orig_node *orig_node,
492 return; 518 return;
493 } 519 }
494 520
495 router = orig_node_get_router(orig_node); 521 if (!is_from_best_next_hop) {
522 /* Mark the forwarded packet when it is not coming from our
523 * best next hop. We still need to forward the packet for our
524 * neighbor link quality detection to work in case the packet
525 * originated from a single hop neighbor. Otherwise we can
526 * simply drop the ogm.
527 */
528 if (is_single_hop_neigh)
529 batman_ogm_packet->flags |= NOT_BEST_NEXT_HOP;
530 else
531 return;
532 }
496 533
497 in_tq = batman_ogm_packet->tq;
498 in_ttl = batman_ogm_packet->header.ttl;
499 tt_num_changes = batman_ogm_packet->tt_num_changes; 534 tt_num_changes = batman_ogm_packet->tt_num_changes;
500 535
501 batman_ogm_packet->header.ttl--; 536 batman_ogm_packet->header.ttl--;
502 memcpy(batman_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); 537 memcpy(batman_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
503 538
504 /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
505 * of our best tq value */
506 if (router && router->tq_avg != 0) {
507
508 /* rebroadcast ogm of best ranking neighbor as is */
509 if (!compare_eth(router->addr, ethhdr->h_source)) {
510 batman_ogm_packet->tq = router->tq_avg;
511
512 if (router->last_ttl)
513 batman_ogm_packet->header.ttl =
514 router->last_ttl - 1;
515 }
516
517 tq_avg = router->tq_avg;
518 }
519
520 if (router)
521 neigh_node_free_ref(router);
522
523 /* apply hop penalty */ 539 /* apply hop penalty */
524 batman_ogm_packet->tq = hop_penalty(batman_ogm_packet->tq, bat_priv); 540 batman_ogm_packet->tq = hop_penalty(batman_ogm_packet->tq, bat_priv);
525 541
526 bat_dbg(DBG_BATMAN, bat_priv, 542 bat_dbg(DBG_BATMAN, bat_priv,
527 "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n", 543 "Forwarding packet: tq: %i, ttl: %i\n",
528 in_tq, tq_avg, batman_ogm_packet->tq, in_ttl - 1, 544 batman_ogm_packet->tq, batman_ogm_packet->header.ttl);
529 batman_ogm_packet->header.ttl);
530 545
531 batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno); 546 batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno);
532 batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc); 547 batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc);
533 548
534 /* switch of primaries first hop flag when forwarding */ 549 /* switch of primaries first hop flag when forwarding */
535 batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP; 550 batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP;
536 if (directlink) 551 if (is_single_hop_neigh)
537 batman_ogm_packet->flags |= DIRECTLINK; 552 batman_ogm_packet->flags |= DIRECTLINK;
538 else 553 else
539 batman_ogm_packet->flags &= ~DIRECTLINK; 554 batman_ogm_packet->flags &= ~DIRECTLINK;
@@ -637,8 +652,9 @@ static void bat_iv_ogm_orig_update(struct bat_priv *bat_priv,
637 if (!orig_tmp) 652 if (!orig_tmp)
638 goto unlock; 653 goto unlock;
639 654
640 neigh_node = create_neighbor(orig_node, orig_tmp, 655 neigh_node = bat_iv_ogm_neigh_new(if_incoming, ethhdr->h_source,
641 ethhdr->h_source, if_incoming); 656 orig_node, orig_tmp,
657 batman_ogm_packet->seqno);
642 658
643 orig_node_free_ref(orig_tmp); 659 orig_node_free_ref(orig_tmp);
644 if (!neigh_node) 660 if (!neigh_node)
@@ -650,7 +666,7 @@ static void bat_iv_ogm_orig_update(struct bat_priv *bat_priv,
650 rcu_read_unlock(); 666 rcu_read_unlock();
651 667
652 orig_node->flags = batman_ogm_packet->flags; 668 orig_node->flags = batman_ogm_packet->flags;
653 neigh_node->last_valid = jiffies; 669 neigh_node->last_seen = jiffies;
654 670
655 spin_lock_bh(&neigh_node->tq_lock); 671 spin_lock_bh(&neigh_node->tq_lock);
656 ring_buffer_set(neigh_node->tq_recv, 672 ring_buffer_set(neigh_node->tq_recv,
@@ -763,19 +779,20 @@ static int bat_iv_ogm_calc_tq(struct orig_node *orig_node,
763 rcu_read_unlock(); 779 rcu_read_unlock();
764 780
765 if (!neigh_node) 781 if (!neigh_node)
766 neigh_node = create_neighbor(orig_neigh_node, 782 neigh_node = bat_iv_ogm_neigh_new(if_incoming,
767 orig_neigh_node, 783 orig_neigh_node->orig,
768 orig_neigh_node->orig, 784 orig_neigh_node,
769 if_incoming); 785 orig_neigh_node,
786 batman_ogm_packet->seqno);
770 787
771 if (!neigh_node) 788 if (!neigh_node)
772 goto out; 789 goto out;
773 790
774 /* if orig_node is direct neighbor update neigh_node last_valid */ 791 /* if orig_node is direct neighbor update neigh_node last_seen */
775 if (orig_node == orig_neigh_node) 792 if (orig_node == orig_neigh_node)
776 neigh_node->last_valid = jiffies; 793 neigh_node->last_seen = jiffies;
777 794
778 orig_node->last_valid = jiffies; 795 orig_node->last_seen = jiffies;
779 796
780 /* find packet count of corresponding one hop neighbor */ 797 /* find packet count of corresponding one hop neighbor */
781 spin_lock_bh(&orig_node->ogm_cnt_lock); 798 spin_lock_bh(&orig_node->ogm_cnt_lock);
@@ -918,7 +935,9 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
918 struct neigh_node *orig_neigh_router = NULL; 935 struct neigh_node *orig_neigh_router = NULL;
919 int has_directlink_flag; 936 int has_directlink_flag;
920 int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; 937 int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
921 int is_broadcast = 0, is_bidirectional, is_single_hop_neigh; 938 int is_broadcast = 0, is_bidirectional;
939 bool is_single_hop_neigh = false;
940 bool is_from_best_next_hop = false;
922 int is_duplicate; 941 int is_duplicate;
923 uint32_t if_incoming_seqno; 942 uint32_t if_incoming_seqno;
924 943
@@ -942,8 +961,8 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
942 961
943 has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0); 962 has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
944 963
945 is_single_hop_neigh = (compare_eth(ethhdr->h_source, 964 if (compare_eth(ethhdr->h_source, batman_ogm_packet->orig))
946 batman_ogm_packet->orig) ? 1 : 0); 965 is_single_hop_neigh = true;
947 966
948 bat_dbg(DBG_BATMAN, bat_priv, 967 bat_dbg(DBG_BATMAN, bat_priv,
949 "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, ttvn %u, crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n", 968 "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, ttvn %u, crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
@@ -1040,6 +1059,13 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
1040 return; 1059 return;
1041 } 1060 }
1042 1061
1062 if (batman_ogm_packet->flags & NOT_BEST_NEXT_HOP) {
1063 bat_dbg(DBG_BATMAN, bat_priv,
1064 "Drop packet: ignoring all packets not forwarded from the best next hop (sender: %pM)\n",
1065 ethhdr->h_source);
1066 return;
1067 }
1068
1043 orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig); 1069 orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig);
1044 if (!orig_node) 1070 if (!orig_node)
1045 return; 1071 return;
@@ -1064,6 +1090,10 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
1064 if (router) 1090 if (router)
1065 router_router = orig_node_get_router(router->orig_node); 1091 router_router = orig_node_get_router(router->orig_node);
1066 1092
1093 if ((router && router->tq_avg != 0) &&
1094 (compare_eth(router->addr, ethhdr->h_source)))
1095 is_from_best_next_hop = true;
1096
1067 /* avoid temporary routing loops */ 1097 /* avoid temporary routing loops */
1068 if (router && router_router && 1098 if (router && router_router &&
1069 (compare_eth(router->addr, batman_ogm_packet->prev_sender)) && 1099 (compare_eth(router->addr, batman_ogm_packet->prev_sender)) &&
@@ -1114,7 +1144,8 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
1114 1144
1115 /* mark direct link on incoming interface */ 1145 /* mark direct link on incoming interface */
1116 bat_iv_ogm_forward(orig_node, ethhdr, batman_ogm_packet, 1146 bat_iv_ogm_forward(orig_node, ethhdr, batman_ogm_packet,
1117 1, if_incoming); 1147 is_single_hop_neigh, is_from_best_next_hop,
1148 if_incoming);
1118 1149
1119 bat_dbg(DBG_BATMAN, bat_priv, 1150 bat_dbg(DBG_BATMAN, bat_priv,
1120 "Forwarding packet: rebroadcast neighbor packet with direct link flag\n"); 1151 "Forwarding packet: rebroadcast neighbor packet with direct link flag\n");
@@ -1137,7 +1168,8 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
1137 bat_dbg(DBG_BATMAN, bat_priv, 1168 bat_dbg(DBG_BATMAN, bat_priv,
1138 "Forwarding packet: rebroadcast originator packet\n"); 1169 "Forwarding packet: rebroadcast originator packet\n");
1139 bat_iv_ogm_forward(orig_node, ethhdr, batman_ogm_packet, 1170 bat_iv_ogm_forward(orig_node, ethhdr, batman_ogm_packet,
1140 0, if_incoming); 1171 is_single_hop_neigh, is_from_best_next_hop,
1172 if_incoming);
1141 1173
1142out_neigh: 1174out_neigh:
1143 if ((orig_neigh_node) && (!is_single_hop_neigh)) 1175 if ((orig_neigh_node) && (!is_single_hop_neigh))
@@ -1153,13 +1185,25 @@ out:
1153 orig_node_free_ref(orig_node); 1185 orig_node_free_ref(orig_node);
1154} 1186}
1155 1187
1156static void bat_iv_ogm_receive(struct hard_iface *if_incoming, 1188static int bat_iv_ogm_receive(struct sk_buff *skb,
1157 struct sk_buff *skb) 1189 struct hard_iface *if_incoming)
1158{ 1190{
1191 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
1159 struct batman_ogm_packet *batman_ogm_packet; 1192 struct batman_ogm_packet *batman_ogm_packet;
1160 struct ethhdr *ethhdr; 1193 struct ethhdr *ethhdr;
1161 int buff_pos = 0, packet_len; 1194 int buff_pos = 0, packet_len;
1162 unsigned char *tt_buff, *packet_buff; 1195 unsigned char *tt_buff, *packet_buff;
1196 bool ret;
1197
1198 ret = check_management_packet(skb, if_incoming, BATMAN_OGM_HLEN);
1199 if (!ret)
1200 return NET_RX_DROP;
1201
1202 /* did we receive a B.A.T.M.A.N. IV OGM packet on an interface
1203 * that does not have B.A.T.M.A.N. IV enabled ?
1204 */
1205 if (bat_priv->bat_algo_ops->bat_ogm_emit != bat_iv_ogm_emit)
1206 return NET_RX_DROP;
1163 1207
1164 packet_len = skb_headlen(skb); 1208 packet_len = skb_headlen(skb);
1165 ethhdr = (struct ethhdr *)skb_mac_header(skb); 1209 ethhdr = (struct ethhdr *)skb_mac_header(skb);
@@ -1185,20 +1229,38 @@ static void bat_iv_ogm_receive(struct hard_iface *if_incoming,
1185 (packet_buff + buff_pos); 1229 (packet_buff + buff_pos);
1186 } while (bat_iv_ogm_aggr_packet(buff_pos, packet_len, 1230 } while (bat_iv_ogm_aggr_packet(buff_pos, packet_len,
1187 batman_ogm_packet->tt_num_changes)); 1231 batman_ogm_packet->tt_num_changes));
1232
1233 kfree_skb(skb);
1234 return NET_RX_SUCCESS;
1188} 1235}
1189 1236
1190static struct bat_algo_ops batman_iv __read_mostly = { 1237static struct bat_algo_ops batman_iv __read_mostly = {
1191 .name = "BATMAN IV", 1238 .name = "BATMAN IV",
1192 .bat_iface_enable = bat_iv_ogm_iface_enable, 1239 .bat_iface_enable = bat_iv_ogm_iface_enable,
1193 .bat_iface_disable = bat_iv_ogm_iface_disable, 1240 .bat_iface_disable = bat_iv_ogm_iface_disable,
1241 .bat_iface_update_mac = bat_iv_ogm_iface_update_mac,
1194 .bat_primary_iface_set = bat_iv_ogm_primary_iface_set, 1242 .bat_primary_iface_set = bat_iv_ogm_primary_iface_set,
1195 .bat_ogm_update_mac = bat_iv_ogm_update_mac,
1196 .bat_ogm_schedule = bat_iv_ogm_schedule, 1243 .bat_ogm_schedule = bat_iv_ogm_schedule,
1197 .bat_ogm_emit = bat_iv_ogm_emit, 1244 .bat_ogm_emit = bat_iv_ogm_emit,
1198 .bat_ogm_receive = bat_iv_ogm_receive,
1199}; 1245};
1200 1246
1201int __init bat_iv_init(void) 1247int __init bat_iv_init(void)
1202{ 1248{
1203 return bat_algo_register(&batman_iv); 1249 int ret;
1250
1251 /* batman originator packet */
1252 ret = recv_handler_register(BAT_IV_OGM, bat_iv_ogm_receive);
1253 if (ret < 0)
1254 goto out;
1255
1256 ret = bat_algo_register(&batman_iv);
1257 if (ret < 0)
1258 goto handler_unregister;
1259
1260 goto out;
1261
1262handler_unregister:
1263 recv_handler_unregister(BAT_IV_OGM);
1264out:
1265 return ret;
1204} 1266}
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index 2c816883ca13..5bc7b66d32dc 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -63,7 +63,7 @@ struct bat_attribute bat_attr_##_name = { \
63 .store = _store, \ 63 .store = _store, \
64}; 64};
65 65
66#define BAT_ATTR_STORE_BOOL(_name, _post_func) \ 66#define BAT_ATTR_SIF_STORE_BOOL(_name, _post_func) \
67ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \ 67ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
68 char *buff, size_t count) \ 68 char *buff, size_t count) \
69{ \ 69{ \
@@ -73,9 +73,9 @@ ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
73 &bat_priv->_name, net_dev); \ 73 &bat_priv->_name, net_dev); \
74} 74}
75 75
76#define BAT_ATTR_SHOW_BOOL(_name) \ 76#define BAT_ATTR_SIF_SHOW_BOOL(_name) \
77ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \ 77ssize_t show_##_name(struct kobject *kobj, \
78 char *buff) \ 78 struct attribute *attr, char *buff) \
79{ \ 79{ \
80 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \ 80 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
81 return sprintf(buff, "%s\n", \ 81 return sprintf(buff, "%s\n", \
@@ -83,16 +83,17 @@ ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
83 "disabled" : "enabled"); \ 83 "disabled" : "enabled"); \
84} \ 84} \
85 85
86/* Use this, if you are going to turn a [name] in bat_priv on or off */ 86/* Use this, if you are going to turn a [name] in the soft-interface
87#define BAT_ATTR_BOOL(_name, _mode, _post_func) \ 87 * (bat_priv) on or off */
88 static BAT_ATTR_STORE_BOOL(_name, _post_func) \ 88#define BAT_ATTR_SIF_BOOL(_name, _mode, _post_func) \
89 static BAT_ATTR_SHOW_BOOL(_name) \ 89 static BAT_ATTR_SIF_STORE_BOOL(_name, _post_func) \
90 static BAT_ATTR_SIF_SHOW_BOOL(_name) \
90 static BAT_ATTR(_name, _mode, show_##_name, store_##_name) 91 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
91 92
92 93
93#define BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \ 94#define BAT_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func) \
94ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \ 95ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
95 char *buff, size_t count) \ 96 char *buff, size_t count) \
96{ \ 97{ \
97 struct net_device *net_dev = kobj_to_netdev(kobj); \ 98 struct net_device *net_dev = kobj_to_netdev(kobj); \
98 struct bat_priv *bat_priv = netdev_priv(net_dev); \ 99 struct bat_priv *bat_priv = netdev_priv(net_dev); \
@@ -100,19 +101,62 @@ ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
100 attr, &bat_priv->_name, net_dev); \ 101 attr, &bat_priv->_name, net_dev); \
101} 102}
102 103
103#define BAT_ATTR_SHOW_UINT(_name) \ 104#define BAT_ATTR_SIF_SHOW_UINT(_name) \
104ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \ 105ssize_t show_##_name(struct kobject *kobj, \
105 char *buff) \ 106 struct attribute *attr, char *buff) \
106{ \ 107{ \
107 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \ 108 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
108 return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name)); \ 109 return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name)); \
109} \ 110} \
110 111
111/* Use this, if you are going to set [name] in bat_priv to unsigned integer 112/* Use this, if you are going to set [name] in the soft-interface
112 * values only */ 113 * (bat_priv) to an unsigned integer value */
113#define BAT_ATTR_UINT(_name, _mode, _min, _max, _post_func) \ 114#define BAT_ATTR_SIF_UINT(_name, _mode, _min, _max, _post_func) \
114 static BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \ 115 static BAT_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func) \
115 static BAT_ATTR_SHOW_UINT(_name) \ 116 static BAT_ATTR_SIF_SHOW_UINT(_name) \
117 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
118
119
120#define BAT_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func) \
121ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
122 char *buff, size_t count) \
123{ \
124 struct net_device *net_dev = kobj_to_netdev(kobj); \
125 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); \
126 ssize_t length; \
127 \
128 if (!hard_iface) \
129 return 0; \
130 \
131 length = __store_uint_attr(buff, count, _min, _max, _post_func, \
132 attr, &hard_iface->_name, net_dev); \
133 \
134 hardif_free_ref(hard_iface); \
135 return length; \
136}
137
138#define BAT_ATTR_HIF_SHOW_UINT(_name) \
139ssize_t show_##_name(struct kobject *kobj, \
140 struct attribute *attr, char *buff) \
141{ \
142 struct net_device *net_dev = kobj_to_netdev(kobj); \
143 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); \
144 ssize_t length; \
145 \
146 if (!hard_iface) \
147 return 0; \
148 \
149 length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\
150 \
151 hardif_free_ref(hard_iface); \
152 return length; \
153}
154
155/* Use this, if you are going to set [name] in hard_iface to an
156 * unsigned integer value*/
157#define BAT_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func) \
158 static BAT_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func) \
159 static BAT_ATTR_HIF_SHOW_UINT(_name) \
116 static BAT_ATTR(_name, _mode, show_##_name, store_##_name) 160 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
117 161
118 162
@@ -384,24 +428,24 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr,
384 return gw_bandwidth_set(net_dev, buff, count); 428 return gw_bandwidth_set(net_dev, buff, count);
385} 429}
386 430
387BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); 431BAT_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
388BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); 432BAT_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
389#ifdef CONFIG_BATMAN_ADV_BLA 433#ifdef CONFIG_BATMAN_ADV_BLA
390BAT_ATTR_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); 434BAT_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
391#endif 435#endif
392BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); 436BAT_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu);
393BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); 437BAT_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
394static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); 438static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
395static BAT_ATTR(routing_algo, S_IRUGO, show_bat_algo, NULL); 439static BAT_ATTR(routing_algo, S_IRUGO, show_bat_algo, NULL);
396static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); 440static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
397BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); 441BAT_ATTR_SIF_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
398BAT_ATTR_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL); 442BAT_ATTR_SIF_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL);
399BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE, 443BAT_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE,
400 post_gw_deselect); 444 post_gw_deselect);
401static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth, 445static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
402 store_gw_bwidth); 446 store_gw_bwidth);
403#ifdef CONFIG_BATMAN_ADV_DEBUG 447#ifdef CONFIG_BATMAN_ADV_DEBUG
404BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 15, NULL); 448BAT_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, 15, NULL);
405#endif 449#endif
406 450
407static struct bat_attribute *mesh_attrs[] = { 451static struct bat_attribute *mesh_attrs[] = {
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index ad394c6496cc..8bf97515a77d 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2011 B.A.T.M.A.N. contributors: 2 * Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
3 * 3 *
4 * Simon Wunderlich 4 * Simon Wunderlich
5 * 5 *
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index 4a8e4fc766bc..e39f93acc28f 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2011 B.A.T.M.A.N. contributors: 2 * Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
3 * 3 *
4 * Simon Wunderlich 4 * Simon Wunderlich
5 * 5 *
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 6f9b9b78f77d..47f7186dcefc 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -558,10 +558,10 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
558 p++; 558 p++;
559 559
560 /* ...and then we jump over the data */ 560 /* ...and then we jump over the data */
561 if (pkt_len < *p) 561 if (pkt_len < 1 + (*p))
562 goto out; 562 goto out;
563 pkt_len -= *p; 563 pkt_len -= 1 + (*p);
564 p += (*p); 564 p += 1 + (*p);
565 } 565 }
566 } 566 }
567out: 567out:
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 47c79d724ba3..0b84bb1b62c4 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -32,12 +32,6 @@
32 32
33#include <linux/if_arp.h> 33#include <linux/if_arp.h>
34 34
35
36static int batman_skb_recv(struct sk_buff *skb,
37 struct net_device *dev,
38 struct packet_type *ptype,
39 struct net_device *orig_dev);
40
41void hardif_free_rcu(struct rcu_head *rcu) 35void hardif_free_rcu(struct rcu_head *rcu)
42{ 36{
43 struct hard_iface *hard_iface; 37 struct hard_iface *hard_iface;
@@ -234,7 +228,7 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
234 228
235 bat_priv = netdev_priv(hard_iface->soft_iface); 229 bat_priv = netdev_priv(hard_iface->soft_iface);
236 230
237 bat_priv->bat_algo_ops->bat_ogm_update_mac(hard_iface); 231 bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface);
238 hard_iface->if_status = IF_TO_BE_ACTIVATED; 232 hard_iface->if_status = IF_TO_BE_ACTIVATED;
239 233
240 /** 234 /**
@@ -530,7 +524,7 @@ static int hard_if_event(struct notifier_block *this,
530 check_known_mac_addr(hard_iface->net_dev); 524 check_known_mac_addr(hard_iface->net_dev);
531 525
532 bat_priv = netdev_priv(hard_iface->soft_iface); 526 bat_priv = netdev_priv(hard_iface->soft_iface);
533 bat_priv->bat_algo_ops->bat_ogm_update_mac(hard_iface); 527 bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface);
534 528
535 primary_if = primary_if_get_selected(bat_priv); 529 primary_if = primary_if_get_selected(bat_priv);
536 if (!primary_if) 530 if (!primary_if)
@@ -551,113 +545,6 @@ out:
551 return NOTIFY_DONE; 545 return NOTIFY_DONE;
552} 546}
553 547
554/* incoming packets with the batman ethertype received on any active hard
555 * interface */
556static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
557 struct packet_type *ptype,
558 struct net_device *orig_dev)
559{
560 struct bat_priv *bat_priv;
561 struct batman_ogm_packet *batman_ogm_packet;
562 struct hard_iface *hard_iface;
563 int ret;
564
565 hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
566 skb = skb_share_check(skb, GFP_ATOMIC);
567
568 /* skb was released by skb_share_check() */
569 if (!skb)
570 goto err_out;
571
572 /* packet should hold at least type and version */
573 if (unlikely(!pskb_may_pull(skb, 2)))
574 goto err_free;
575
576 /* expect a valid ethernet header here. */
577 if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
578 goto err_free;
579
580 if (!hard_iface->soft_iface)
581 goto err_free;
582
583 bat_priv = netdev_priv(hard_iface->soft_iface);
584
585 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
586 goto err_free;
587
588 /* discard frames on not active interfaces */
589 if (hard_iface->if_status != IF_ACTIVE)
590 goto err_free;
591
592 batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
593
594 if (batman_ogm_packet->header.version != COMPAT_VERSION) {
595 bat_dbg(DBG_BATMAN, bat_priv,
596 "Drop packet: incompatible batman version (%i)\n",
597 batman_ogm_packet->header.version);
598 goto err_free;
599 }
600
601 /* all receive handlers return whether they received or reused
602 * the supplied skb. if not, we have to free the skb. */
603
604 switch (batman_ogm_packet->header.packet_type) {
605 /* batman originator packet */
606 case BAT_IV_OGM:
607 ret = recv_bat_ogm_packet(skb, hard_iface);
608 break;
609
610 /* batman icmp packet */
611 case BAT_ICMP:
612 ret = recv_icmp_packet(skb, hard_iface);
613 break;
614
615 /* unicast packet */
616 case BAT_UNICAST:
617 ret = recv_unicast_packet(skb, hard_iface);
618 break;
619
620 /* fragmented unicast packet */
621 case BAT_UNICAST_FRAG:
622 ret = recv_ucast_frag_packet(skb, hard_iface);
623 break;
624
625 /* broadcast packet */
626 case BAT_BCAST:
627 ret = recv_bcast_packet(skb, hard_iface);
628 break;
629
630 /* vis packet */
631 case BAT_VIS:
632 ret = recv_vis_packet(skb, hard_iface);
633 break;
634 /* Translation table query (request or response) */
635 case BAT_TT_QUERY:
636 ret = recv_tt_query(skb, hard_iface);
637 break;
638 /* Roaming advertisement */
639 case BAT_ROAM_ADV:
640 ret = recv_roam_adv(skb, hard_iface);
641 break;
642 default:
643 ret = NET_RX_DROP;
644 }
645
646 if (ret == NET_RX_DROP)
647 kfree_skb(skb);
648
649 /* return NET_RX_SUCCESS in any case as we
650 * most probably dropped the packet for
651 * routing-logical reasons. */
652
653 return NET_RX_SUCCESS;
654
655err_free:
656 kfree_skb(skb);
657err_out:
658 return NET_RX_DROP;
659}
660
661/* This function returns true if the interface represented by ifindex is a 548/* This function returns true if the interface represented by ifindex is a
662 * 802.11 wireless device */ 549 * 802.11 wireless device */
663bool is_wifi_iface(int ifindex) 550bool is_wifi_iface(int ifindex)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 791327219531..083a2993efe4 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -39,6 +39,7 @@
39/* List manipulations on hardif_list have to be rtnl_lock()'ed, 39/* List manipulations on hardif_list have to be rtnl_lock()'ed,
40 * list traversals just rcu-locked */ 40 * list traversals just rcu-locked */
41struct list_head hardif_list; 41struct list_head hardif_list;
42static int (*recv_packet_handler[256])(struct sk_buff *, struct hard_iface *);
42char bat_routing_algo[20] = "BATMAN IV"; 43char bat_routing_algo[20] = "BATMAN IV";
43static struct hlist_head bat_algo_list; 44static struct hlist_head bat_algo_list;
44 45
@@ -46,11 +47,15 @@ unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
46 47
47struct workqueue_struct *bat_event_workqueue; 48struct workqueue_struct *bat_event_workqueue;
48 49
50static void recv_handler_init(void);
51
49static int __init batman_init(void) 52static int __init batman_init(void)
50{ 53{
51 INIT_LIST_HEAD(&hardif_list); 54 INIT_LIST_HEAD(&hardif_list);
52 INIT_HLIST_HEAD(&bat_algo_list); 55 INIT_HLIST_HEAD(&bat_algo_list);
53 56
57 recv_handler_init();
58
54 bat_iv_init(); 59 bat_iv_init();
55 60
56 /* the name should not be longer than 10 chars - see 61 /* the name should not be longer than 10 chars - see
@@ -179,6 +184,120 @@ int is_my_mac(const uint8_t *addr)
179 return 0; 184 return 0;
180} 185}
181 186
187static int recv_unhandled_packet(struct sk_buff *skb,
188 struct hard_iface *recv_if)
189{
190 return NET_RX_DROP;
191}
192
193/* incoming packets with the batman ethertype received on any active hard
194 * interface
195 */
196int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
197 struct packet_type *ptype, struct net_device *orig_dev)
198{
199 struct bat_priv *bat_priv;
200 struct batman_ogm_packet *batman_ogm_packet;
201 struct hard_iface *hard_iface;
202 uint8_t idx;
203 int ret;
204
205 hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
206 skb = skb_share_check(skb, GFP_ATOMIC);
207
208 /* skb was released by skb_share_check() */
209 if (!skb)
210 goto err_out;
211
212 /* packet should hold at least type and version */
213 if (unlikely(!pskb_may_pull(skb, 2)))
214 goto err_free;
215
216 /* expect a valid ethernet header here. */
217 if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
218 goto err_free;
219
220 if (!hard_iface->soft_iface)
221 goto err_free;
222
223 bat_priv = netdev_priv(hard_iface->soft_iface);
224
225 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
226 goto err_free;
227
228 /* discard frames on not active interfaces */
229 if (hard_iface->if_status != IF_ACTIVE)
230 goto err_free;
231
232 batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
233
234 if (batman_ogm_packet->header.version != COMPAT_VERSION) {
235 bat_dbg(DBG_BATMAN, bat_priv,
236 "Drop packet: incompatible batman version (%i)\n",
237 batman_ogm_packet->header.version);
238 goto err_free;
239 }
240
241 /* all receive handlers return whether they received or reused
242 * the supplied skb. if not, we have to free the skb.
243 */
244 idx = batman_ogm_packet->header.packet_type;
245 ret = (*recv_packet_handler[idx])(skb, hard_iface);
246
247 if (ret == NET_RX_DROP)
248 kfree_skb(skb);
249
250 /* return NET_RX_SUCCESS in any case as we
251 * most probably dropped the packet for
252 * routing-logical reasons.
253 */
254 return NET_RX_SUCCESS;
255
256err_free:
257 kfree_skb(skb);
258err_out:
259 return NET_RX_DROP;
260}
261
262static void recv_handler_init(void)
263{
264 int i;
265
266 for (i = 0; i < ARRAY_SIZE(recv_packet_handler); i++)
267 recv_packet_handler[i] = recv_unhandled_packet;
268
269 /* batman icmp packet */
270 recv_packet_handler[BAT_ICMP] = recv_icmp_packet;
271 /* unicast packet */
272 recv_packet_handler[BAT_UNICAST] = recv_unicast_packet;
273 /* fragmented unicast packet */
274 recv_packet_handler[BAT_UNICAST_FRAG] = recv_ucast_frag_packet;
275 /* broadcast packet */
276 recv_packet_handler[BAT_BCAST] = recv_bcast_packet;
277 /* vis packet */
278 recv_packet_handler[BAT_VIS] = recv_vis_packet;
279 /* Translation table query (request or response) */
280 recv_packet_handler[BAT_TT_QUERY] = recv_tt_query;
281 /* Roaming advertisement */
282 recv_packet_handler[BAT_ROAM_ADV] = recv_roam_adv;
283}
284
285int recv_handler_register(uint8_t packet_type,
286 int (*recv_handler)(struct sk_buff *,
287 struct hard_iface *))
288{
289 if (recv_packet_handler[packet_type] != &recv_unhandled_packet)
290 return -EBUSY;
291
292 recv_packet_handler[packet_type] = recv_handler;
293 return 0;
294}
295
296void recv_handler_unregister(uint8_t packet_type)
297{
298 recv_packet_handler[packet_type] = recv_unhandled_packet;
299}
300
182static struct bat_algo_ops *bat_algo_get(char *name) 301static struct bat_algo_ops *bat_algo_get(char *name)
183{ 302{
184 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp; 303 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp;
@@ -210,11 +329,10 @@ int bat_algo_register(struct bat_algo_ops *bat_algo_ops)
210 /* all algorithms must implement all ops (for now) */ 329 /* all algorithms must implement all ops (for now) */
211 if (!bat_algo_ops->bat_iface_enable || 330 if (!bat_algo_ops->bat_iface_enable ||
212 !bat_algo_ops->bat_iface_disable || 331 !bat_algo_ops->bat_iface_disable ||
332 !bat_algo_ops->bat_iface_update_mac ||
213 !bat_algo_ops->bat_primary_iface_set || 333 !bat_algo_ops->bat_primary_iface_set ||
214 !bat_algo_ops->bat_ogm_update_mac ||
215 !bat_algo_ops->bat_ogm_schedule || 334 !bat_algo_ops->bat_ogm_schedule ||
216 !bat_algo_ops->bat_ogm_emit || 335 !bat_algo_ops->bat_ogm_emit) {
217 !bat_algo_ops->bat_ogm_receive) {
218 pr_info("Routing algo '%s' does not implement required ops\n", 336 pr_info("Routing algo '%s' does not implement required ops\n",
219 bat_algo_ops->name); 337 bat_algo_ops->name);
220 goto out; 338 goto out;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index d9832acf558d..fd83acd48b28 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -155,6 +155,12 @@ void mesh_free(struct net_device *soft_iface);
155void inc_module_count(void); 155void inc_module_count(void);
156void dec_module_count(void); 156void dec_module_count(void);
157int is_my_mac(const uint8_t *addr); 157int is_my_mac(const uint8_t *addr);
158int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
159 struct packet_type *ptype, struct net_device *orig_dev);
160int recv_handler_register(uint8_t packet_type,
161 int (*recv_handler)(struct sk_buff *,
162 struct hard_iface *));
163void recv_handler_unregister(uint8_t packet_type);
158int bat_algo_register(struct bat_algo_ops *bat_algo_ops); 164int bat_algo_register(struct bat_algo_ops *bat_algo_ops);
159int bat_algo_select(struct bat_priv *bat_priv, char *name); 165int bat_algo_select(struct bat_priv *bat_priv, char *name);
160int bat_algo_seq_print_text(struct seq_file *seq, void *offset); 166int bat_algo_seq_print_text(struct seq_file *seq, void *offset);
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index ce4969885894..f4b62011ca3f 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -35,7 +35,8 @@ static void purge_orig(struct work_struct *work);
35static void start_purge_timer(struct bat_priv *bat_priv) 35static void start_purge_timer(struct bat_priv *bat_priv)
36{ 36{
37 INIT_DELAYED_WORK(&bat_priv->orig_work, purge_orig); 37 INIT_DELAYED_WORK(&bat_priv->orig_work, purge_orig);
38 queue_delayed_work(bat_event_workqueue, &bat_priv->orig_work, 1 * HZ); 38 queue_delayed_work(bat_event_workqueue,
39 &bat_priv->orig_work, msecs_to_jiffies(1000));
39} 40}
40 41
41/* returns 1 if they are the same originator */ 42/* returns 1 if they are the same originator */
@@ -84,35 +85,29 @@ struct neigh_node *orig_node_get_router(struct orig_node *orig_node)
84 return router; 85 return router;
85} 86}
86 87
87struct neigh_node *create_neighbor(struct orig_node *orig_node, 88struct neigh_node *batadv_neigh_node_new(struct hard_iface *hard_iface,
88 struct orig_node *orig_neigh_node, 89 const uint8_t *neigh_addr,
89 const uint8_t *neigh, 90 uint32_t seqno)
90 struct hard_iface *if_incoming)
91{ 91{
92 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 92 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
93 struct neigh_node *neigh_node; 93 struct neigh_node *neigh_node;
94 94
95 bat_dbg(DBG_BATMAN, bat_priv,
96 "Creating new last-hop neighbor of originator\n");
97
98 neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC); 95 neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
99 if (!neigh_node) 96 if (!neigh_node)
100 return NULL; 97 goto out;
101 98
102 INIT_HLIST_NODE(&neigh_node->list); 99 INIT_HLIST_NODE(&neigh_node->list);
103 INIT_LIST_HEAD(&neigh_node->bonding_list);
104 spin_lock_init(&neigh_node->tq_lock);
105 100
106 memcpy(neigh_node->addr, neigh, ETH_ALEN); 101 memcpy(neigh_node->addr, neigh_addr, ETH_ALEN);
107 neigh_node->orig_node = orig_neigh_node;
108 neigh_node->if_incoming = if_incoming;
109 102
110 /* extra reference for return */ 103 /* extra reference for return */
111 atomic_set(&neigh_node->refcount, 2); 104 atomic_set(&neigh_node->refcount, 2);
112 105
113 spin_lock_bh(&orig_node->neigh_list_lock); 106 bat_dbg(DBG_BATMAN, bat_priv,
114 hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); 107 "Creating new neighbor %pM, initial seqno %d\n",
115 spin_unlock_bh(&orig_node->neigh_list_lock); 108 neigh_addr, seqno);
109
110out:
116 return neigh_node; 111 return neigh_node;
117} 112}
118 113
@@ -274,6 +269,7 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
274 struct hlist_node *node, *node_tmp; 269 struct hlist_node *node, *node_tmp;
275 struct neigh_node *neigh_node; 270 struct neigh_node *neigh_node;
276 bool neigh_purged = false; 271 bool neigh_purged = false;
272 unsigned long last_seen;
277 273
278 *best_neigh_node = NULL; 274 *best_neigh_node = NULL;
279 275
@@ -283,11 +279,13 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
283 hlist_for_each_entry_safe(neigh_node, node, node_tmp, 279 hlist_for_each_entry_safe(neigh_node, node, node_tmp,
284 &orig_node->neigh_list, list) { 280 &orig_node->neigh_list, list) {
285 281
286 if ((has_timed_out(neigh_node->last_valid, PURGE_TIMEOUT)) || 282 if ((has_timed_out(neigh_node->last_seen, PURGE_TIMEOUT)) ||
287 (neigh_node->if_incoming->if_status == IF_INACTIVE) || 283 (neigh_node->if_incoming->if_status == IF_INACTIVE) ||
288 (neigh_node->if_incoming->if_status == IF_NOT_IN_USE) || 284 (neigh_node->if_incoming->if_status == IF_NOT_IN_USE) ||
289 (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) { 285 (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) {
290 286
287 last_seen = neigh_node->last_seen;
288
291 if ((neigh_node->if_incoming->if_status == 289 if ((neigh_node->if_incoming->if_status ==
292 IF_INACTIVE) || 290 IF_INACTIVE) ||
293 (neigh_node->if_incoming->if_status == 291 (neigh_node->if_incoming->if_status ==
@@ -300,9 +298,9 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
300 neigh_node->if_incoming->net_dev->name); 298 neigh_node->if_incoming->net_dev->name);
301 else 299 else
302 bat_dbg(DBG_BATMAN, bat_priv, 300 bat_dbg(DBG_BATMAN, bat_priv,
303 "neighbor timeout: originator %pM, neighbor: %pM, last_valid: %lu\n", 301 "neighbor timeout: originator %pM, neighbor: %pM, last_seen: %u\n",
304 orig_node->orig, neigh_node->addr, 302 orig_node->orig, neigh_node->addr,
305 (neigh_node->last_valid / HZ)); 303 jiffies_to_msecs(last_seen));
306 304
307 neigh_purged = true; 305 neigh_purged = true;
308 306
@@ -325,10 +323,11 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
325{ 323{
326 struct neigh_node *best_neigh_node; 324 struct neigh_node *best_neigh_node;
327 325
328 if (has_timed_out(orig_node->last_valid, 2 * PURGE_TIMEOUT)) { 326 if (has_timed_out(orig_node->last_seen, 2 * PURGE_TIMEOUT)) {
329 bat_dbg(DBG_BATMAN, bat_priv, 327 bat_dbg(DBG_BATMAN, bat_priv,
330 "Originator timeout: originator %pM, last_valid %lu\n", 328 "Originator timeout: originator %pM, last_seen %u\n",
331 orig_node->orig, (orig_node->last_valid / HZ)); 329 orig_node->orig,
330 jiffies_to_msecs(orig_node->last_seen));
332 return true; 331 return true;
333 } else { 332 } else {
334 if (purge_orig_neighbors(bat_priv, orig_node, 333 if (purge_orig_neighbors(bat_priv, orig_node,
@@ -446,9 +445,9 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
446 goto next; 445 goto next;
447 446
448 last_seen_secs = jiffies_to_msecs(jiffies - 447 last_seen_secs = jiffies_to_msecs(jiffies -
449 orig_node->last_valid) / 1000; 448 orig_node->last_seen) / 1000;
450 last_seen_msecs = jiffies_to_msecs(jiffies - 449 last_seen_msecs = jiffies_to_msecs(jiffies -
451 orig_node->last_valid) % 1000; 450 orig_node->last_seen) % 1000;
452 451
453 seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", 452 seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:",
454 orig_node->orig, last_seen_secs, 453 orig_node->orig, last_seen_secs,
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 3fe2eda85652..f74d0d693359 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -29,10 +29,9 @@ void originator_free(struct bat_priv *bat_priv);
29void purge_orig_ref(struct bat_priv *bat_priv); 29void purge_orig_ref(struct bat_priv *bat_priv);
30void orig_node_free_ref(struct orig_node *orig_node); 30void orig_node_free_ref(struct orig_node *orig_node);
31struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr); 31struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr);
32struct neigh_node *create_neighbor(struct orig_node *orig_node, 32struct neigh_node *batadv_neigh_node_new(struct hard_iface *hard_iface,
33 struct orig_node *orig_neigh_node, 33 const uint8_t *neigh_addr,
34 const uint8_t *neigh, 34 uint32_t seqno);
35 struct hard_iface *if_incoming);
36void neigh_node_free_ref(struct neigh_node *neigh_node); 35void neigh_node_free_ref(struct neigh_node *neigh_node);
37struct neigh_node *orig_node_get_router(struct orig_node *orig_node); 36struct neigh_node *orig_node_get_router(struct orig_node *orig_node);
38int orig_seq_print_text(struct seq_file *seq, void *offset); 37int orig_seq_print_text(struct seq_file *seq, void *offset);
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index f54969c61a1e..0ee1af770798 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -39,6 +39,7 @@ enum bat_packettype {
39#define COMPAT_VERSION 14 39#define COMPAT_VERSION 14
40 40
41enum batman_iv_flags { 41enum batman_iv_flags {
42 NOT_BEST_NEXT_HOP = 1 << 3,
42 PRIMARIES_FIRST_HOP = 1 << 4, 43 PRIMARIES_FIRST_HOP = 1 << 4,
43 VIS_SERVER = 1 << 5, 44 VIS_SERVER = 1 << 5,
44 DIRECTLINK = 1 << 6 45 DIRECTLINK = 1 << 6
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index ff560863bc74..7ed9d8f92916 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -248,37 +248,35 @@ int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff,
248 return 0; 248 return 0;
249} 249}
250 250
251int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *hard_iface) 251bool check_management_packet(struct sk_buff *skb,
252 struct hard_iface *hard_iface,
253 int header_len)
252{ 254{
253 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
254 struct ethhdr *ethhdr; 255 struct ethhdr *ethhdr;
255 256
256 /* drop packet if it has not necessary minimum size */ 257 /* drop packet if it has not necessary minimum size */
257 if (unlikely(!pskb_may_pull(skb, BATMAN_OGM_HLEN))) 258 if (unlikely(!pskb_may_pull(skb, header_len)))
258 return NET_RX_DROP; 259 return false;
259 260
260 ethhdr = (struct ethhdr *)skb_mac_header(skb); 261 ethhdr = (struct ethhdr *)skb_mac_header(skb);
261 262
262 /* packet with broadcast indication but unicast recipient */ 263 /* packet with broadcast indication but unicast recipient */
263 if (!is_broadcast_ether_addr(ethhdr->h_dest)) 264 if (!is_broadcast_ether_addr(ethhdr->h_dest))
264 return NET_RX_DROP; 265 return false;
265 266
266 /* packet with broadcast sender address */ 267 /* packet with broadcast sender address */
267 if (is_broadcast_ether_addr(ethhdr->h_source)) 268 if (is_broadcast_ether_addr(ethhdr->h_source))
268 return NET_RX_DROP; 269 return false;
269 270
270 /* create a copy of the skb, if needed, to modify it. */ 271 /* create a copy of the skb, if needed, to modify it. */
271 if (skb_cow(skb, 0) < 0) 272 if (skb_cow(skb, 0) < 0)
272 return NET_RX_DROP; 273 return false;
273 274
274 /* keep skb linear */ 275 /* keep skb linear */
275 if (skb_linearize(skb) < 0) 276 if (skb_linearize(skb) < 0)
276 return NET_RX_DROP; 277 return false;
277
278 bat_priv->bat_algo_ops->bat_ogm_receive(hard_iface, skb);
279 278
280 kfree_skb(skb); 279 return true;
281 return NET_RX_SUCCESS;
282} 280}
283 281
284static int recv_my_icmp_packet(struct bat_priv *bat_priv, 282static int recv_my_icmp_packet(struct bat_priv *bat_priv,
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 3d729cb17113..d6bbbebb6567 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -23,6 +23,9 @@
23#define _NET_BATMAN_ADV_ROUTING_H_ 23#define _NET_BATMAN_ADV_ROUTING_H_
24 24
25void slide_own_bcast_window(struct hard_iface *hard_iface); 25void slide_own_bcast_window(struct hard_iface *hard_iface);
26bool check_management_packet(struct sk_buff *skb,
27 struct hard_iface *hard_iface,
28 int header_len);
26void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, 29void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node,
27 struct neigh_node *neigh_node); 30 struct neigh_node *neigh_node);
28int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); 31int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if);
@@ -30,7 +33,6 @@ int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
30int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if); 33int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if);
31int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if); 34int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
32int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if); 35int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
33int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *recv_if);
34int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if); 36int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if);
35int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if); 37int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if);
36struct neigh_node *find_router(struct bat_priv *bat_priv, 38struct neigh_node *find_router(struct bat_priv *bat_priv,
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 7c66b6121fa6..8e74d9763be3 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -292,7 +292,7 @@ static void send_outstanding_bcast_packet(struct work_struct *work)
292 /* if we still have some more bcasts to send */ 292 /* if we still have some more bcasts to send */
293 if (forw_packet->num_packets < 3) { 293 if (forw_packet->num_packets < 3) {
294 _add_bcast_packet_to_list(bat_priv, forw_packet, 294 _add_bcast_packet_to_list(bat_priv, forw_packet,
295 ((5 * HZ) / 1000)); 295 msecs_to_jiffies(5));
296 return; 296 return;
297 } 297 }
298 298
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index a38d315d3cd6..2cb46f0bb163 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: 2 * Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
3 * 3 *
4 * Marek Lindner, Simon Wunderlich 4 * Marek Lindner, Simon Wunderlich, Antonio Quartulli
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public 7 * modify it under the terms of version 2 of the GNU General Public
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index bfebe26edd8e..593d1b31217c 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: 2 * Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
3 * 3 *
4 * Marek Lindner, Simon Wunderlich 4 * Marek Lindner, Simon Wunderlich, Antonio Quartulli
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public 7 * modify it under the terms of version 2 of the GNU General Public
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 2f4848b776a7..66a3750aa9e7 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -52,7 +52,7 @@ struct hard_iface {
52/** 52/**
53 * orig_node - structure for orig_list maintaining nodes of mesh 53 * orig_node - structure for orig_list maintaining nodes of mesh
54 * @primary_addr: hosts primary interface address 54 * @primary_addr: hosts primary interface address
55 * @last_valid: when last packet from this node was received 55 * @last_seen: when last packet from this node was received
56 * @bcast_seqno_reset: time when the broadcast seqno window was reset 56 * @bcast_seqno_reset: time when the broadcast seqno window was reset
57 * @batman_seqno_reset: time when the batman seqno window was reset 57 * @batman_seqno_reset: time when the batman seqno window was reset
58 * @gw_flags: flags related to gateway class 58 * @gw_flags: flags related to gateway class
@@ -70,7 +70,7 @@ struct orig_node {
70 struct neigh_node __rcu *router; /* rcu protected pointer */ 70 struct neigh_node __rcu *router; /* rcu protected pointer */
71 unsigned long *bcast_own; 71 unsigned long *bcast_own;
72 uint8_t *bcast_own_sum; 72 uint8_t *bcast_own_sum;
73 unsigned long last_valid; 73 unsigned long last_seen;
74 unsigned long bcast_seqno_reset; 74 unsigned long bcast_seqno_reset;
75 unsigned long batman_seqno_reset; 75 unsigned long batman_seqno_reset;
76 uint8_t gw_flags; 76 uint8_t gw_flags;
@@ -120,7 +120,7 @@ struct gw_node {
120 120
121/** 121/**
122 * neigh_node 122 * neigh_node
123 * @last_valid: when last packet via this neighbor was received 123 * @last_seen: when last packet via this neighbor was received
124 */ 124 */
125struct neigh_node { 125struct neigh_node {
126 struct hlist_node list; 126 struct hlist_node list;
@@ -131,7 +131,7 @@ struct neigh_node {
131 uint8_t tq_avg; 131 uint8_t tq_avg;
132 uint8_t last_ttl; 132 uint8_t last_ttl;
133 struct list_head bonding_list; 133 struct list_head bonding_list;
134 unsigned long last_valid; 134 unsigned long last_seen;
135 DECLARE_BITMAP(real_bits, TQ_LOCAL_WINDOW_SIZE); 135 DECLARE_BITMAP(real_bits, TQ_LOCAL_WINDOW_SIZE);
136 atomic_t refcount; 136 atomic_t refcount;
137 struct rcu_head rcu; 137 struct rcu_head rcu;
@@ -381,18 +381,17 @@ struct bat_algo_ops {
381 int (*bat_iface_enable)(struct hard_iface *hard_iface); 381 int (*bat_iface_enable)(struct hard_iface *hard_iface);
382 /* de-init routing info when hard-interface is disabled */ 382 /* de-init routing info when hard-interface is disabled */
383 void (*bat_iface_disable)(struct hard_iface *hard_iface); 383 void (*bat_iface_disable)(struct hard_iface *hard_iface);
384 /* (re-)init mac addresses of the protocol information
385 * belonging to this hard-interface
386 */
387 void (*bat_iface_update_mac)(struct hard_iface *hard_iface);
384 /* called when primary interface is selected / changed */ 388 /* called when primary interface is selected / changed */
385 void (*bat_primary_iface_set)(struct hard_iface *hard_iface); 389 void (*bat_primary_iface_set)(struct hard_iface *hard_iface);
386 /* init mac addresses of the OGM belonging to this hard-interface */
387 void (*bat_ogm_update_mac)(struct hard_iface *hard_iface);
388 /* prepare a new outgoing OGM for the send queue */ 390 /* prepare a new outgoing OGM for the send queue */
389 void (*bat_ogm_schedule)(struct hard_iface *hard_iface, 391 void (*bat_ogm_schedule)(struct hard_iface *hard_iface,
390 int tt_num_changes); 392 int tt_num_changes);
391 /* send scheduled OGM */ 393 /* send scheduled OGM */
392 void (*bat_ogm_emit)(struct forw_packet *forw_packet); 394 void (*bat_ogm_emit)(struct forw_packet *forw_packet);
393 /* receive incoming OGM */
394 void (*bat_ogm_receive)(struct hard_iface *if_incoming,
395 struct sk_buff *skb);
396}; 395};
397 396
398#endif /* _NET_BATMAN_ADV_TYPES_H_ */ 397#endif /* _NET_BATMAN_ADV_TYPES_H_ */