aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/bat_iv_ogm.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-06-19 19:49:39 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-19 19:49:39 -0400
commitd98cae64e4a733ff377184d78aa0b1f2b54faede (patch)
treee973e3c93fe7e17741567ac3947f5197bc9d582d /net/batman-adv/bat_iv_ogm.c
parent646093a29f85630d8efe2aa38fa585d2c3ea2e46 (diff)
parent4067c666f2dccf56f5db5c182713e68c40d46013 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/wireless/ath/ath9k/Kconfig drivers/net/xen-netback/netback.c net/batman-adv/bat_iv_ogm.c net/wireless/nl80211.c The ath9k Kconfig conflict was a change of a Kconfig option name right next to the deletion of another option. The xen-netback conflict was overlapping changes involving the handling of the notify list in xen_netbk_rx_action(). Batman conflict resolution provided by Antonio Quartulli, basically keep everything in both conflict hunks. The nl80211 conflict is a little more involved. In 'net' we added a dynamic memory allocation to nl80211_dump_wiphy() to fix a race that Linus reported. Meanwhile in 'net-next' the handlers were converted to use pre and post doit handlers which use a flag to determine whether to hold the RTNL mutex around the operation. However, the dump handlers to not use this logic. Instead they have to explicitly do the locking. There were apparent bugs in the conversion of nl80211_dump_wiphy() in that we were not dropping the RTNL mutex in all the return paths, and it seems we very much should be doing so. So I fixed that whilst handling the overlapping changes. To simplify the initial returns, I take the RTNL mutex after we try to allocate 'tb'. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/batman-adv/bat_iv_ogm.c')
-rw-r--r--net/batman-adv/bat_iv_ogm.c87
1 files changed, 56 insertions, 31 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index d07323b3e9b8..62da5278014a 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -70,6 +70,22 @@ static uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[])
70 70
71 return (uint8_t)(sum / count); 71 return (uint8_t)(sum / count);
72} 72}
73
74/*
75 * batadv_dup_status - duplicate status
76 * @BATADV_NO_DUP: the packet is a duplicate
77 * @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the
78 * neighbor)
79 * @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor
80 * @BATADV_PROTECTED: originator is currently protected (after reboot)
81 */
82enum batadv_dup_status {
83 BATADV_NO_DUP = 0,
84 BATADV_ORIG_DUP,
85 BATADV_NEIGH_DUP,
86 BATADV_PROTECTED,
87};
88
73static struct batadv_neigh_node * 89static struct batadv_neigh_node *
74batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, 90batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
75 const uint8_t *neigh_addr, 91 const uint8_t *neigh_addr,
@@ -723,7 +739,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
723 const struct batadv_ogm_packet *batadv_ogm_packet, 739 const struct batadv_ogm_packet *batadv_ogm_packet,
724 struct batadv_hard_iface *if_incoming, 740 struct batadv_hard_iface *if_incoming,
725 const unsigned char *tt_buff, 741 const unsigned char *tt_buff,
726 int is_duplicate) 742 enum batadv_dup_status dup_status)
727{ 743{
728 struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; 744 struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
729 struct batadv_neigh_node *router = NULL; 745 struct batadv_neigh_node *router = NULL;
@@ -749,7 +765,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
749 continue; 765 continue;
750 } 766 }
751 767
752 if (is_duplicate) 768 if (dup_status != BATADV_NO_DUP)
753 continue; 769 continue;
754 770
755 spin_lock_bh(&tmp_neigh_node->lq_update_lock); 771 spin_lock_bh(&tmp_neigh_node->lq_update_lock);
@@ -790,7 +806,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
790 neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv); 806 neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv);
791 spin_unlock_bh(&neigh_node->lq_update_lock); 807 spin_unlock_bh(&neigh_node->lq_update_lock);
792 808
793 if (!is_duplicate) { 809 if (dup_status == BATADV_NO_DUP) {
794 orig_node->last_ttl = batadv_ogm_packet->header.ttl; 810 orig_node->last_ttl = batadv_ogm_packet->header.ttl;
795 neigh_node->last_ttl = batadv_ogm_packet->header.ttl; 811 neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
796 } 812 }
@@ -973,15 +989,16 @@ out:
973 return ret; 989 return ret;
974} 990}
975 991
976/* processes a batman packet for all interfaces, adjusts the sequence number and 992/**
977 * finds out whether it is a duplicate. 993 * batadv_iv_ogm_update_seqnos - process a batman packet for all interfaces,
978 * returns: 994 * adjust the sequence number and find out whether it is a duplicate
979 * 1 the packet is a duplicate 995 * @ethhdr: ethernet header of the packet
980 * 0 the packet has not yet been received 996 * @batadv_ogm_packet: OGM packet to be considered
981 * -1 the packet is old and has been received while the seqno window 997 * @if_incoming: interface on which the OGM packet was received
982 * was protected. Caller should drop it. 998 *
999 * Returns duplicate status as enum batadv_dup_status
983 */ 1000 */
984static int 1001static enum batadv_dup_status
985batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, 1002batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
986 const struct batadv_ogm_packet *batadv_ogm_packet, 1003 const struct batadv_ogm_packet *batadv_ogm_packet,
987 const struct batadv_hard_iface *if_incoming) 1004 const struct batadv_hard_iface *if_incoming)
@@ -989,17 +1006,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
989 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 1006 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
990 struct batadv_orig_node *orig_node; 1007 struct batadv_orig_node *orig_node;
991 struct batadv_neigh_node *tmp_neigh_node; 1008 struct batadv_neigh_node *tmp_neigh_node;
992 int is_duplicate = 0; 1009 int is_dup;
993 int32_t seq_diff; 1010 int32_t seq_diff;
994 int need_update = 0; 1011 int need_update = 0;
995 int set_mark, ret = -1; 1012 int set_mark;
1013 enum batadv_dup_status ret = BATADV_NO_DUP;
996 uint32_t seqno = ntohl(batadv_ogm_packet->seqno); 1014 uint32_t seqno = ntohl(batadv_ogm_packet->seqno);
997 uint8_t *neigh_addr; 1015 uint8_t *neigh_addr;
998 uint8_t packet_count; 1016 uint8_t packet_count;
999 1017
1000 orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); 1018 orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig);
1001 if (!orig_node) 1019 if (!orig_node)
1002 return 0; 1020 return BATADV_NO_DUP;
1003 1021
1004 spin_lock_bh(&orig_node->ogm_cnt_lock); 1022 spin_lock_bh(&orig_node->ogm_cnt_lock);
1005 seq_diff = seqno - orig_node->last_real_seqno; 1023 seq_diff = seqno - orig_node->last_real_seqno;
@@ -1007,22 +1025,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
1007 /* signalize caller that the packet is to be dropped. */ 1025 /* signalize caller that the packet is to be dropped. */
1008 if (!hlist_empty(&orig_node->neigh_list) && 1026 if (!hlist_empty(&orig_node->neigh_list) &&
1009 batadv_window_protected(bat_priv, seq_diff, 1027 batadv_window_protected(bat_priv, seq_diff,
1010 &orig_node->batman_seqno_reset)) 1028 &orig_node->batman_seqno_reset)) {
1029 ret = BATADV_PROTECTED;
1011 goto out; 1030 goto out;
1031 }
1012 1032
1013 rcu_read_lock(); 1033 rcu_read_lock();
1014 hlist_for_each_entry_rcu(tmp_neigh_node, 1034 hlist_for_each_entry_rcu(tmp_neigh_node,
1015 &orig_node->neigh_list, list) { 1035 &orig_node->neigh_list, list) {
1016 is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits,
1017 orig_node->last_real_seqno,
1018 seqno);
1019
1020 neigh_addr = tmp_neigh_node->addr; 1036 neigh_addr = tmp_neigh_node->addr;
1037 is_dup = batadv_test_bit(tmp_neigh_node->real_bits,
1038 orig_node->last_real_seqno,
1039 seqno);
1040
1021 if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && 1041 if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
1022 tmp_neigh_node->if_incoming == if_incoming) 1042 tmp_neigh_node->if_incoming == if_incoming) {
1023 set_mark = 1; 1043 set_mark = 1;
1024 else 1044 if (is_dup)
1045 ret = BATADV_NEIGH_DUP;
1046 } else {
1025 set_mark = 0; 1047 set_mark = 0;
1048 if (is_dup && (ret != BATADV_NEIGH_DUP))
1049 ret = BATADV_ORIG_DUP;
1050 }
1026 1051
1027 /* if the window moved, set the update flag. */ 1052 /* if the window moved, set the update flag. */
1028 need_update |= batadv_bit_get_packet(bat_priv, 1053 need_update |= batadv_bit_get_packet(bat_priv,
@@ -1042,8 +1067,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
1042 orig_node->last_real_seqno = seqno; 1067 orig_node->last_real_seqno = seqno;
1043 } 1068 }
1044 1069
1045 ret = is_duplicate;
1046
1047out: 1070out:
1048 spin_unlock_bh(&orig_node->ogm_cnt_lock); 1071 spin_unlock_bh(&orig_node->ogm_cnt_lock);
1049 batadv_orig_node_free_ref(orig_node); 1072 batadv_orig_node_free_ref(orig_node);
@@ -1065,7 +1088,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1065 int is_bidirect; 1088 int is_bidirect;
1066 bool is_single_hop_neigh = false; 1089 bool is_single_hop_neigh = false;
1067 bool is_from_best_next_hop = false; 1090 bool is_from_best_next_hop = false;
1068 int is_duplicate, sameseq, simlar_ttl; 1091 int sameseq, similar_ttl;
1092 enum batadv_dup_status dup_status;
1069 uint32_t if_incoming_seqno; 1093 uint32_t if_incoming_seqno;
1070 uint8_t *prev_sender; 1094 uint8_t *prev_sender;
1071 1095
@@ -1192,10 +1216,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1192 if (!orig_node) 1216 if (!orig_node)
1193 return; 1217 return;
1194 1218
1195 is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, 1219 dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
1196 if_incoming); 1220 if_incoming);
1197 1221
1198 if (is_duplicate == -1) { 1222 if (dup_status == BATADV_PROTECTED) {
1199 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1223 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1200 "Drop packet: packet within seqno protection time (sender: %pM)\n", 1224 "Drop packet: packet within seqno protection time (sender: %pM)\n",
1201 ethhdr->h_source); 1225 ethhdr->h_source);
@@ -1265,11 +1289,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1265 * seqno and similar ttl as the non-duplicate 1289 * seqno and similar ttl as the non-duplicate
1266 */ 1290 */
1267 sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); 1291 sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
1268 simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl; 1292 similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
1269 if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl))) 1293 if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
1294 (sameseq && similar_ttl)))
1270 batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, 1295 batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
1271 batadv_ogm_packet, if_incoming, 1296 batadv_ogm_packet, if_incoming,
1272 tt_buff, is_duplicate); 1297 tt_buff, dup_status);
1273 1298
1274 /* is single hop (direct) neighbor */ 1299 /* is single hop (direct) neighbor */
1275 if (is_single_hop_neigh) { 1300 if (is_single_hop_neigh) {
@@ -1290,7 +1315,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1290 goto out_neigh; 1315 goto out_neigh;
1291 } 1316 }
1292 1317
1293 if (is_duplicate) { 1318 if (dup_status == BATADV_NEIGH_DUP) {
1294 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1319 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1295 "Drop packet: duplicate packet received\n"); 1320 "Drop packet: duplicate packet received\n");
1296 goto out_neigh; 1321 goto out_neigh;