The following commit has been merged in the merge/master branch: commit 79ce8b58aff393d904dbbcc0e3059135e2efca40 Merge: 209f023fc09dda7ef78ffba555bb7b6e47459dfe 11d07bad4b5bd703d6b60ef088877fa782a2dc69 Author: Antonio Quartulli ordex@autistici.org Date: Wed Aug 22 00:21:53 2012 +0200
Merge remote-tracking branch 'pkg/next' into merge/master
Conflicts: net/batman-adv/CHANGELOG net/batman-adv/README net/batman-adv/README.external net/batman-adv/bridge_loop_avoidance.h
diff --combined Documentation/networking/batman-adv.txt index 8f3ae4a,a173d2a..a173d2a --- a/Documentation/networking/batman-adv.txt +++ b/Documentation/networking/batman-adv.txt @@@ -75,9 -75,10 +75,10 @@@ folder
There is a special folder for debugging information:
- # ls /sys/kernel/debug/batman_adv/bat0/ - # bla_claim_table log socket transtable_local - # gateways originators transtable_global vis_data + # ls /sys/kernel/debug/batman_adv/bat0/ + # bla_backbone_table log transtable_global + # bla_claim_table originators transtable_local + # gateways socket vis_data
Some of the files contain all sort of status information regard- ing the mesh network. For example, you can view the table of diff --combined net/batman-adv/bat_iv_ogm.c index e877af8,df79300..df79300 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@@ -166,13 -166,15 +166,15 @@@ static void batadv_iv_ogm_send_to_if(st int16_t buff_pos; struct batadv_ogm_packet *batadv_ogm_packet; struct sk_buff *skb; + uint8_t *packet_pos;
if (hard_iface->if_status != BATADV_IF_ACTIVE) return;
packet_num = 0; buff_pos = 0; - batadv_ogm_packet = (struct batadv_ogm_packet *)forw_packet->skb->data; + packet_pos = forw_packet->skb->data; + batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
/* adjust all flags and log packets */ while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, @@@ -181,15 -183,17 +183,17 @@@ /* we might have aggregated direct link packets with an * ordinary base packet */ - if ((forw_packet->direct_link_flags & (1 << packet_num)) && - (forw_packet->if_incoming == hard_iface)) + if (forw_packet->direct_link_flags & BIT(packet_num) && + forw_packet->if_incoming == hard_iface) batadv_ogm_packet->flags |= BATADV_DIRECTLINK; else batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK;
- fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? - "Sending own" : - "Forwarding")); + if (packet_num > 0 || !forw_packet->own) + fwd_str = "Forwarding"; + else + fwd_str = "Sending own"; + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n", fwd_str, (packet_num > 0 ? "aggregated " : ""), @@@ -204,8 -208,8 +208,8 @@@ buff_pos += BATADV_OGM_HLEN; buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); packet_num++; - batadv_ogm_packet = (struct batadv_ogm_packet *) - (forw_packet->skb->data + buff_pos); + packet_pos = forw_packet->skb->data + buff_pos; + batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; }
/* create clone because function is called more than once */ @@@ -227,9 -231,10 +231,10 @@@ static void batadv_iv_ogm_emit(struct b struct batadv_hard_iface *primary_if = NULL; struct batadv_ogm_packet *batadv_ogm_packet; unsigned char directlink; + uint8_t *packet_pos;
- batadv_ogm_packet = (struct batadv_ogm_packet *) - (forw_packet->skb->data); + packet_pos = forw_packet->skb->data; + batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; directlink = (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) { @@@ -454,6 -459,7 +459,7 @@@ static void batadv_iv_ogm_aggregate(str int packet_len, bool direct_link) { unsigned char *skb_buff; + unsigned long new_direct_link_flag;
skb_buff = skb_put(forw_packet_aggr->skb, packet_len); memcpy(skb_buff, packet_buff, packet_len); @@@ -461,9 -467,10 +467,10 @@@ forw_packet_aggr->num_packets++;
/* save packet direct link flag status */ - if (direct_link) - forw_packet_aggr->direct_link_flags |= - (1 << forw_packet_aggr->num_packets); + if (direct_link) { + new_direct_link_flag = BIT(forw_packet_aggr->num_packets); + forw_packet_aggr->direct_link_flags |= new_direct_link_flag; + } }
static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, @@@ -586,6 -593,8 +593,8 @@@ static void batadv_iv_ogm_schedule(stru struct batadv_ogm_packet *batadv_ogm_packet; struct batadv_hard_iface *primary_if; int vis_server, tt_num_changes = 0; + uint32_t seqno; + uint8_t bandwidth;
vis_server = atomic_read(&bat_priv->vis_mode); primary_if = batadv_primary_if_get_selected(bat_priv); @@@ -599,12 -608,12 +608,12 @@@ batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
/* change sequence number to network order */ - batadv_ogm_packet->seqno = - htonl((uint32_t)atomic_read(&hard_iface->seqno)); + seqno = (uint32_t)atomic_read(&hard_iface->seqno); + batadv_ogm_packet->seqno = htonl(seqno); atomic_inc(&hard_iface->seqno);
- batadv_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn); - batadv_ogm_packet->tt_crc = htons(bat_priv->tt_crc); + batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn); + batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc); if (tt_num_changes >= 0) batadv_ogm_packet->tt_num_changes = tt_num_changes;
@@@ -613,12 -622,13 +622,13 @@@ else batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER;
- if ((hard_iface == primary_if) && - (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER)) - batadv_ogm_packet->gw_flags = - (uint8_t)atomic_read(&bat_priv->gw_bandwidth); - else + if (hard_iface == primary_if && + atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) { + bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); + batadv_ogm_packet->gw_flags = bandwidth; + } else { batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS; + }
batadv_slide_own_bcast_window(hard_iface); batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff, @@@ -642,8 -652,9 +652,9 @@@ batadv_iv_ogm_orig_update(struct batadv struct batadv_neigh_node *router = NULL; struct batadv_orig_node *orig_node_tmp; struct hlist_node *node; - uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; + uint8_t sum_orig, sum_neigh; uint8_t *neigh_addr; + uint8_t tq_avg;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "update_originator(): Searching and updating originator entry of received packet\n"); @@@ -667,8 -678,8 +678,8 @@@ spin_lock_bh(&tmp_neigh_node->lq_update_lock); batadv_ring_buffer_set(tmp_neigh_node->tq_recv, &tmp_neigh_node->tq_index, 0); - tmp_neigh_node->tq_avg = - batadv_ring_buffer_avg(tmp_neigh_node->tq_recv); + tq_avg = batadv_ring_buffer_avg(tmp_neigh_node->tq_recv); + tmp_neigh_node->tq_avg = tq_avg; spin_unlock_bh(&tmp_neigh_node->lq_update_lock); }
@@@ -727,17 -738,15 +738,15 @@@ if (router && (neigh_node->tq_avg == router->tq_avg)) { orig_node_tmp = router->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - bcast_own_sum_orig = - orig_node_tmp->bcast_own_sum[if_incoming->if_num]; + sum_orig = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
orig_node_tmp = neigh_node->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - bcast_own_sum_neigh = - orig_node_tmp->bcast_own_sum[if_incoming->if_num]; + sum_neigh = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
- if (bcast_own_sum_orig >= bcast_own_sum_neigh) + if (sum_orig >= sum_neigh) goto update_tt; }
@@@ -835,8 -844,10 +844,10 @@@ static int batadv_iv_ogm_calc_tq(struc spin_unlock_bh(&orig_node->ogm_cnt_lock);
/* pay attention to not get a value bigger than 100 % */ - total_count = (orig_eq_count > neigh_rq_count ? - neigh_rq_count : orig_eq_count); + if (orig_eq_count > neigh_rq_count) + total_count = neigh_rq_count; + else + total_count = orig_eq_count;
/* if we have too few packets (too less data) we set tq_own to zero * if we receive too few packets it is not considered bidirectional @@@ -910,6 -921,7 +921,7 @@@ batadv_iv_ogm_update_seqnos(const struc int set_mark, ret = -1; uint32_t seqno = ntohl(batadv_ogm_packet->seqno); uint8_t *neigh_addr; + uint8_t packet_count;
orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); if (!orig_node) @@@ -944,9 -956,9 +956,9 @@@ tmp_neigh_node->real_bits, seq_diff, set_mark);
- tmp_neigh_node->real_packet_count = - bitmap_weight(tmp_neigh_node->real_bits, - BATADV_TQ_LOCAL_WINDOW_SIZE); + packet_count = bitmap_weight(tmp_neigh_node->real_bits, + BATADV_TQ_LOCAL_WINDOW_SIZE); + tmp_neigh_node->real_packet_count = packet_count; } rcu_read_unlock();
@@@ -1163,9 -1175,12 +1175,12 @@@ static void batadv_iv_ogm_process(cons /* if sender is a direct neighbor the sender mac equals * originator mac */ - orig_neigh_node = (is_single_hop_neigh ? - orig_node : - batadv_get_orig_node(bat_priv, ethhdr->h_source)); + if (is_single_hop_neigh) + orig_neigh_node = orig_node; + else + orig_neigh_node = batadv_get_orig_node(bat_priv, + ethhdr->h_source); + if (!orig_neigh_node) goto out;
@@@ -1251,6 -1266,7 +1266,7 @@@ static int batadv_iv_ogm_receive(struc int buff_pos = 0, packet_len; unsigned char *tt_buff, *packet_buff; bool ret; + uint8_t *packet_pos;
ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); if (!ret) @@@ -1281,8 -1297,8 +1297,8 @@@ buff_pos += BATADV_OGM_HLEN; buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes);
- batadv_ogm_packet = (struct batadv_ogm_packet *) - (packet_buff + buff_pos); + packet_pos = packet_buff + buff_pos; + batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; } while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, batadv_ogm_packet->tt_num_changes));
diff --combined net/batman-adv/bridge_loop_avoidance.c index 6705d35,0a9084a..0a9084a --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@@ -133,7 -133,7 +133,7 @@@ static void batadv_claim_free_ref(struc static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv, struct batadv_claim *data) { - struct batadv_hashtable *hash = bat_priv->claim_hash; + struct batadv_hashtable *hash = bat_priv->bla.claim_hash; struct hlist_head *head; struct hlist_node *node; struct batadv_claim *claim; @@@ -174,7 -174,7 +174,7 @@@ static struct batadv_backbone_gw batadv_backbone_hash_find(struct batadv_priv *bat_priv, uint8_t *addr, short vid) { - struct batadv_hashtable *hash = bat_priv->backbone_hash; + struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; struct hlist_head *head; struct hlist_node *node; struct batadv_backbone_gw search_entry, *backbone_gw; @@@ -218,7 -218,7 +218,7 @@@ batadv_bla_del_backbone_claims(struct b int i; spinlock_t *list_lock; /* protects write access to the hash lists */
- hash = backbone_gw->bat_priv->claim_hash; + hash = backbone_gw->bat_priv->bla.claim_hash; if (!hash) return;
@@@ -265,7 -265,7 +265,7 @@@ static void batadv_bla_send_claim(struc if (!primary_if) return;
- memcpy(&local_claim_dest, &bat_priv->claim_dest, + memcpy(&local_claim_dest, &bat_priv->bla.claim_dest, sizeof(local_claim_dest)); local_claim_dest.type = claimtype;
@@@ -281,7 -281,7 +281,7 @@@ NULL, /* Ethernet SRC/HW SRC: originator mac */ primary_if->net_dev->dev_addr, - /* HW DST: FF:43:05:XX:00:00 + /* HW DST: FF:43:05:XX:YY:YY * with XX = claim type * and YY:YY = group id */ @@@ -295,7 -295,7 +295,7 @@@
/* now we pretend that the client would have sent this ... */ switch (claimtype) { - case BATADV_CLAIM_TYPE_ADD: + case BATADV_CLAIM_TYPE_CLAIM: /* normal claim frame * set Ethernet SRC to the clients mac */ @@@ -303,7 -303,7 +303,7 @@@ batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid); break; - case BATADV_CLAIM_TYPE_DEL: + case BATADV_CLAIM_TYPE_UNCLAIM: /* unclaim frame * set HW SRC to the clients mac */ @@@ -323,7 -323,8 +323,8 @@@ break; case BATADV_CLAIM_TYPE_REQUEST: /* request frame - * set HW SRC to the special mac containg the crc + * set HW SRC and header destination to the receiving backbone + * gws mac */ memcpy(hw_src, mac, ETH_ALEN); memcpy(ethhdr->h_dest, mac, ETH_ALEN); @@@ -339,8 -340,9 +340,9 @@@
skb_reset_mac_header(skb); skb->protocol = eth_type_trans(skb, soft_iface); - bat_priv->stats.rx_packets++; - bat_priv->stats.rx_bytes += skb->len + ETH_HLEN; + batadv_inc_counter(bat_priv, BATADV_CNT_RX); + batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, + skb->len + ETH_HLEN); soft_iface->last_rx = jiffies;
netif_rx(skb); @@@ -389,7 -391,7 +391,7 @@@ batadv_bla_get_backbone_gw(struct batad /* one for the hash, one for returning */ atomic_set(&entry->refcount, 2);
- hash_added = batadv_hash_add(bat_priv->backbone_hash, + hash_added = batadv_hash_add(bat_priv->bla.backbone_hash, batadv_compare_backbone_gw, batadv_choose_backbone_gw, entry, &entry->hash_entry); @@@ -456,7 -458,7 +458,7 @@@ static void batadv_bla_answer_request(s if (!backbone_gw) return;
- hash = bat_priv->claim_hash; + hash = bat_priv->bla.claim_hash; for (i = 0; i < hash->size; i++) { head = &hash->table[i];
@@@ -467,7 -469,7 +469,7 @@@ continue;
batadv_bla_send_claim(bat_priv, claim->addr, claim->vid, - BATADV_CLAIM_TYPE_ADD); + BATADV_CLAIM_TYPE_CLAIM); } rcu_read_unlock(); } @@@ -497,7 -499,7 +499,7 @@@ static void batadv_bla_send_request(str
/* no local broadcasts should be sent or received, for now. */ if (!atomic_read(&backbone_gw->request_sent)) { - atomic_inc(&backbone_gw->bat_priv->bla_num_requests); + atomic_inc(&backbone_gw->bat_priv->bla.num_requests); atomic_set(&backbone_gw->request_sent, 1); } } @@@ -557,7 -559,7 +559,7 @@@ static void batadv_bla_add_claim(struc batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n", mac, vid); - hash_added = batadv_hash_add(bat_priv->claim_hash, + hash_added = batadv_hash_add(bat_priv->bla.claim_hash, batadv_compare_claim, batadv_choose_claim, claim, &claim->hash_entry); @@@ -577,8 -579,7 +579,7 @@@ "bla_add_claim(): changing ownership for %pM, vid %d\n", mac, vid);
- claim->backbone_gw->crc ^= - crc16(0, claim->addr, ETH_ALEN); + claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); batadv_backbone_gw_free_ref(claim->backbone_gw);
} @@@ -610,7 -611,7 +611,7 @@@ static void batadv_bla_del_claim(struc batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n", mac, vid);
- batadv_hash_remove(bat_priv->claim_hash, batadv_compare_claim, + batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim, batadv_choose_claim, claim); batadv_claim_free_ref(claim); /* reference from the hash is gone */
@@@ -657,7 -658,7 +658,7 @@@ static int batadv_handle_announce(struc * we can allow traffic again. */ if (atomic_read(&backbone_gw->request_sent)) { - atomic_dec(&backbone_gw->bat_priv->bla_num_requests); + atomic_dec(&backbone_gw->bat_priv->bla.num_requests); atomic_set(&backbone_gw->request_sent, 0); } } @@@ -702,7 -703,7 +703,7 @@@ static int batadv_handle_unclaim(struc if (primary_if && batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr)) batadv_bla_send_claim(bat_priv, claim_addr, vid, - BATADV_CLAIM_TYPE_DEL); + BATADV_CLAIM_TYPE_UNCLAIM);
backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
@@@ -738,7 -739,7 +739,7 @@@ static int batadv_handle_claim(struct b batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw); if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr)) batadv_bla_send_claim(bat_priv, claim_addr, vid, - BATADV_CLAIM_TYPE_ADD); + BATADV_CLAIM_TYPE_CLAIM);
/* TODO: we could call something like tt_local_del() here. */
@@@ -772,7 -773,7 +773,7 @@@ static int batadv_check_claim_group(str struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
bla_dst = (struct batadv_bla_claim_dst *)hw_dst; - bla_dst_own = &bat_priv->claim_dest; + bla_dst_own = &bat_priv->bla.claim_dest;
/* check if it is a claim packet in general */ if (memcmp(bla_dst->magic, bla_dst_own->magic, @@@ -783,12 -784,12 +784,12 @@@ * otherwise assume it is in the hw_src */ switch (bla_dst->type) { - case BATADV_CLAIM_TYPE_ADD: + case BATADV_CLAIM_TYPE_CLAIM: backbone_addr = hw_src; break; case BATADV_CLAIM_TYPE_REQUEST: case BATADV_CLAIM_TYPE_ANNOUNCE: - case BATADV_CLAIM_TYPE_DEL: + case BATADV_CLAIM_TYPE_UNCLAIM: backbone_addr = ethhdr->h_source; break; default: @@@ -904,12 -905,12 +905,12 @@@ static int batadv_bla_process_claim(str
/* check for the different types of claim frames ... */ switch (bla_dst->type) { - case BATADV_CLAIM_TYPE_ADD: + case BATADV_CLAIM_TYPE_CLAIM: if (batadv_handle_claim(bat_priv, primary_if, hw_src, ethhdr->h_source, vid)) return 1; break; - case BATADV_CLAIM_TYPE_DEL: + case BATADV_CLAIM_TYPE_UNCLAIM: if (batadv_handle_unclaim(bat_priv, primary_if, ethhdr->h_source, hw_src, vid)) return 1; @@@ -945,7 -946,7 +946,7 @@@ static void batadv_bla_purge_backbone_g spinlock_t *list_lock; /* protects write access to the hash lists */ int i;
- hash = bat_priv->backbone_hash; + hash = bat_priv->bla.backbone_hash; if (!hash) return;
@@@ -969,7 -970,7 +970,7 @@@ purge_now: /* don't wait for the pending request anymore */ if (atomic_read(&backbone_gw->request_sent)) - atomic_dec(&bat_priv->bla_num_requests); + atomic_dec(&bat_priv->bla.num_requests);
batadv_bla_del_backbone_claims(backbone_gw);
@@@ -999,7 -1000,7 +1000,7 @@@ static void batadv_bla_purge_claims(str struct batadv_hashtable *hash; int i;
- hash = bat_priv->claim_hash; + hash = bat_priv->bla.claim_hash; if (!hash) return;
@@@ -1046,11 -1047,12 +1047,12 @@@ void batadv_bla_update_orig_address(str struct hlist_node *node; struct hlist_head *head; struct batadv_hashtable *hash; + __be16 group; int i;
/* reset bridge loop avoidance group id */ - bat_priv->claim_dest.group = - htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); + group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); + bat_priv->bla.claim_dest.group = group;
if (!oldif) { batadv_bla_purge_claims(bat_priv, NULL, 1); @@@ -1058,7 -1060,7 +1060,7 @@@ return; }
- hash = bat_priv->backbone_hash; + hash = bat_priv->bla.backbone_hash; if (!hash) return;
@@@ -1088,8 -1090,8 +1090,8 @@@ /* (re)start the timer */ static void batadv_bla_start_timer(struct batadv_priv *bat_priv) { - INIT_DELAYED_WORK(&bat_priv->bla_work, batadv_bla_periodic_work); - queue_delayed_work(batadv_event_workqueue, &bat_priv->bla_work, + INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work); + queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work, msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH)); }
@@@ -1099,9 -1101,9 +1101,9 @@@ */ static void batadv_bla_periodic_work(struct work_struct *work) { - struct delayed_work *delayed_work = - container_of(work, struct delayed_work, work); + struct delayed_work *delayed_work; struct batadv_priv *bat_priv; + struct batadv_priv_bla *priv_bla; struct hlist_node *node; struct hlist_head *head; struct batadv_backbone_gw *backbone_gw; @@@ -1109,7 -1111,9 +1111,9 @@@ struct batadv_hard_iface *primary_if; int i;
- bat_priv = container_of(delayed_work, struct batadv_priv, bla_work); + delayed_work = container_of(work, struct delayed_work, work); + priv_bla = container_of(delayed_work, struct batadv_priv_bla, work); + bat_priv = container_of(priv_bla, struct batadv_priv, bla); primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out; @@@ -1120,7 -1124,7 +1124,7 @@@ if (!atomic_read(&bat_priv->bridge_loop_avoidance)) goto out;
- hash = bat_priv->backbone_hash; + hash = bat_priv->bla.backbone_hash; if (!hash) goto out;
@@@ -1160,40 -1164,41 +1164,41 @@@ int batadv_bla_init(struct batadv_priv int i; uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00}; struct batadv_hard_iface *primary_if; + uint16_t crc; + unsigned long entrytime;
batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
/* setting claim destination address */ - memcpy(&bat_priv->claim_dest.magic, claim_dest, 3); - bat_priv->claim_dest.type = 0; + memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3); + bat_priv->bla.claim_dest.type = 0; primary_if = batadv_primary_if_get_selected(bat_priv); if (primary_if) { - bat_priv->claim_dest.group = - htons(crc16(0, primary_if->net_dev->dev_addr, - ETH_ALEN)); + crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN); + bat_priv->bla.claim_dest.group = htons(crc); batadv_hardif_free_ref(primary_if); } else { - bat_priv->claim_dest.group = 0; /* will be set later */ + bat_priv->bla.claim_dest.group = 0; /* will be set later */ }
/* initialize the duplicate list */ + entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT); for (i = 0; i < BATADV_DUPLIST_SIZE; i++) - bat_priv->bcast_duplist[i].entrytime = - jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT); - bat_priv->bcast_duplist_curr = 0; + bat_priv->bla.bcast_duplist[i].entrytime = entrytime; + bat_priv->bla.bcast_duplist_curr = 0;
- if (bat_priv->claim_hash) + if (bat_priv->bla.claim_hash) return 0;
- bat_priv->claim_hash = batadv_hash_new(128); - bat_priv->backbone_hash = batadv_hash_new(32); + bat_priv->bla.claim_hash = batadv_hash_new(128); + bat_priv->bla.backbone_hash = batadv_hash_new(32);
- if (!bat_priv->claim_hash || !bat_priv->backbone_hash) + if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash) return -ENOMEM;
- batadv_hash_set_lock_class(bat_priv->claim_hash, + batadv_hash_set_lock_class(bat_priv->bla.claim_hash, &batadv_claim_hash_lock_class_key); - batadv_hash_set_lock_class(bat_priv->backbone_hash, + batadv_hash_set_lock_class(bat_priv->bla.backbone_hash, &batadv_backbone_hash_lock_class_key);
batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n"); @@@ -1234,8 -1239,9 +1239,9 @@@ int batadv_bla_check_bcast_duplist(stru crc = crc16(0, content, length);
for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { - curr = (bat_priv->bcast_duplist_curr + i) % BATADV_DUPLIST_SIZE; - entry = &bat_priv->bcast_duplist[curr]; + curr = (bat_priv->bla.bcast_duplist_curr + i); + curr %= BATADV_DUPLIST_SIZE; + entry = &bat_priv->bla.bcast_duplist[curr];
/* we can stop searching if the entry is too old ; * later entries will be even older @@@ -1256,13 -1262,13 +1262,13 @@@ return 1; } /* not found, add a new entry (overwrite the oldest entry) */ - curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); + curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); curr %= BATADV_DUPLIST_SIZE; - entry = &bat_priv->bcast_duplist[curr]; + entry = &bat_priv->bla.bcast_duplist[curr]; entry->crc = crc; entry->entrytime = jiffies; memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); - bat_priv->bcast_duplist_curr = curr; + bat_priv->bla.bcast_duplist_curr = curr;
/* allow it, its the first occurence. */ return 0; @@@ -1279,7 -1285,7 +1285,7 @@@ */ int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig) { - struct batadv_hashtable *hash = bat_priv->backbone_hash; + struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; struct hlist_head *head; struct hlist_node *node; struct batadv_backbone_gw *backbone_gw; @@@ -1339,8 -1345,7 +1345,7 @@@ int batadv_bla_is_backbone_gw(struct sk if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr))) return 0;
- vhdr = (struct vlan_ethhdr *)(((uint8_t *)skb->data) + - hdr_size); + vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size); vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; }
@@@ -1359,18 -1364,18 +1364,18 @@@ void batadv_bla_free(struct batadv_pri { struct batadv_hard_iface *primary_if;
- cancel_delayed_work_sync(&bat_priv->bla_work); + cancel_delayed_work_sync(&bat_priv->bla.work); primary_if = batadv_primary_if_get_selected(bat_priv);
- if (bat_priv->claim_hash) { + if (bat_priv->bla.claim_hash) { batadv_bla_purge_claims(bat_priv, primary_if, 1); - batadv_hash_destroy(bat_priv->claim_hash); - bat_priv->claim_hash = NULL; + batadv_hash_destroy(bat_priv->bla.claim_hash); + bat_priv->bla.claim_hash = NULL; } - if (bat_priv->backbone_hash) { + if (bat_priv->bla.backbone_hash) { batadv_bla_purge_backbone_gw(bat_priv, 1); - batadv_hash_destroy(bat_priv->backbone_hash); - bat_priv->backbone_hash = NULL; + batadv_hash_destroy(bat_priv->bla.backbone_hash); + bat_priv->bla.backbone_hash = NULL; } if (primary_if) batadv_hardif_free_ref(primary_if); @@@ -1409,7 -1414,7 +1414,7 @@@ int batadv_bla_rx(struct batadv_priv *b goto allow;
- if (unlikely(atomic_read(&bat_priv->bla_num_requests))) + if (unlikely(atomic_read(&bat_priv->bla.num_requests))) /* don't allow broadcasts while requests are in flight */ if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) goto handled; @@@ -1508,7 -1513,7 +1513,7 @@@ int batadv_bla_tx(struct batadv_priv *b
ethhdr = (struct ethhdr *)skb_mac_header(skb);
- if (unlikely(atomic_read(&bat_priv->bla_num_requests))) + if (unlikely(atomic_read(&bat_priv->bla.num_requests))) /* don't allow broadcasts while requests are in flight */ if (is_multicast_ether_addr(ethhdr->h_dest)) goto handled; @@@ -1564,7 -1569,7 +1569,7 @@@ int batadv_bla_claim_table_seq_print_te { struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_priv *bat_priv = netdev_priv(net_dev); - struct batadv_hashtable *hash = bat_priv->claim_hash; + struct batadv_hashtable *hash = bat_priv->bla.claim_hash; struct batadv_claim *claim; struct batadv_hard_iface *primary_if; struct hlist_node *node; @@@ -1593,7 -1598,7 +1598,7 @@@ seq_printf(seq, "Claims announced for the mesh %s (orig %pM, group id %04x)\n", net_dev->name, primary_addr, - ntohs(bat_priv->claim_dest.group)); + ntohs(bat_priv->bla.claim_dest.group)); seq_printf(seq, " %-17s %-5s %-17s [o] (%-4s)\n", "Client", "VID", "Originator", "CRC"); for (i = 0; i < hash->size; i++) { @@@ -1616,3 -1621,68 +1621,68 @@@ out batadv_hardif_free_ref(primary_if); return ret; } + + int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) + { + struct net_device *net_dev = (struct net_device *)seq->private; + struct batadv_priv *bat_priv = netdev_priv(net_dev); + struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; + struct batadv_backbone_gw *backbone_gw; + struct batadv_hard_iface *primary_if; + struct hlist_node *node; + struct hlist_head *head; + int secs, msecs; + uint32_t i; + bool is_own; + int ret = 0; + uint8_t *primary_addr; + + primary_if = batadv_primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, + "BATMAN mesh %s disabled - please specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != BATADV_IF_ACTIVE) { + ret = seq_printf(seq, + "BATMAN mesh %s disabled - primary interface not active\n", + net_dev->name); + goto out; + } + + primary_addr = primary_if->net_dev->dev_addr; + seq_printf(seq, + "Backbones announced for the mesh %s (orig %pM, group id %04x)\n", + net_dev->name, primary_addr, + ntohs(bat_priv->bla.claim_dest.group)); + seq_printf(seq, " %-17s %-5s %-9s (%-4s)\n", + "Originator", "VID", "last seen", "CRC"); + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) { + msecs = jiffies_to_msecs(jiffies - + backbone_gw->lasttime); + secs = msecs / 1000; + msecs = msecs % 1000; + + is_own = batadv_compare_eth(backbone_gw->orig, + primary_addr); + if (is_own) + continue; + + seq_printf(seq, + " * %pM on % 5d % 4i.%03is (%04x)\n", + backbone_gw->orig, backbone_gw->vid, + secs, msecs, backbone_gw->crc); + } + rcu_read_unlock(); + } + out: + if (primary_if) + batadv_hardif_free_ref(primary_if); + return ret; + } diff --combined net/batman-adv/bridge_loop_avoidance.h index 563cfbf,0000000..e04a8fe mode 100644,000000..100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h @@@ -1,101 -1,0 +1,109 @@@ +/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors: + * + * Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef _NET_BATMAN_ADV_BLA_H_ +#define _NET_BATMAN_ADV_BLA_H_ + +#ifdef CONFIG_BATMAN_ADV_BLA +int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, + bool is_bcast); +int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid); +int batadv_bla_is_backbone_gw(struct sk_buff *skb, + struct batadv_orig_node *orig_node, int hdr_size); +int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset); ++int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, ++ void *offset); +int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig); +int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, + struct batadv_bcast_packet *bcast_packet, + int hdr_size); +void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, + struct batadv_hard_iface *primary_if, + struct batadv_hard_iface *oldif); +int batadv_bla_init(struct batadv_priv *bat_priv); +void batadv_bla_free(struct batadv_priv *bat_priv); + +#define BATADV_BLA_CRC_INIT 0 +#else /* ifdef CONFIG_BATMAN_ADV_BLA */ + +static inline int batadv_bla_rx(struct batadv_priv *bat_priv, + struct sk_buff *skb, short vid, + bool is_bcast) +{ + return 0; +} + +static inline int batadv_bla_tx(struct batadv_priv *bat_priv, + struct sk_buff *skb, short vid) +{ + return 0; +} + +static inline int batadv_bla_is_backbone_gw(struct sk_buff *skb, + struct batadv_orig_node *orig_node, + int hdr_size) +{ + return 0; +} + +static inline int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, + void *offset) +{ + return 0; +} + ++static inline int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, ++ void *offset) ++{ ++ return 0; ++} ++ +static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, + uint8_t *orig) +{ + return 0; +} + +static inline int +batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, + struct batadv_bcast_packet *bcast_packet, + int hdr_size) +{ + return 0; +} + +static inline void +batadv_bla_update_orig_address(struct batadv_priv *bat_priv, + struct batadv_hard_iface *primary_if, + struct batadv_hard_iface *oldif) +{ +} + +static inline int batadv_bla_init(struct batadv_priv *bat_priv) +{ + return 1; +} + +static inline void batadv_bla_free(struct batadv_priv *bat_priv) +{ +} + +#endif /* ifdef CONFIG_BATMAN_ADV_BLA */ + +#endif /* ifndef _NET_BATMAN_ADV_BLA_H_ */ diff --combined net/batman-adv/debugfs.c index 34fbb16,391d4fb..391d4fb --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@@ -267,6 -267,15 +267,15 @@@ static int batadv_bla_claim_table_open( return single_open(file, batadv_bla_claim_table_seq_print_text, net_dev); } + + static int batadv_bla_backbone_table_open(struct inode *inode, + struct file *file) + { + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, batadv_bla_backbone_table_seq_print_text, + net_dev); + } + #endif
static int batadv_transtable_local_open(struct inode *inode, struct file *file) @@@ -305,6 -314,8 +314,8 @@@ static BATADV_DEBUGINFO(transtable_glob batadv_transtable_global_open); #ifdef CONFIG_BATMAN_ADV_BLA static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open); + static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO, + batadv_bla_backbone_table_open); #endif static BATADV_DEBUGINFO(transtable_local, S_IRUGO, batadv_transtable_local_open); @@@ -316,6 -327,7 +327,7 @@@ static struct batadv_debuginfo *batadv_ &batadv_debuginfo_transtable_global, #ifdef CONFIG_BATMAN_ADV_BLA &batadv_debuginfo_bla_claim_table, + &batadv_debuginfo_bla_backbone_table, #endif &batadv_debuginfo_transtable_local, &batadv_debuginfo_vis_data, diff --combined net/batman-adv/gateway_client.c index b421cc4,15d67ab..15d67ab --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@@ -48,7 -48,7 +48,7 @@@ batadv_gw_get_selected_gw_node(struct b struct batadv_gw_node *gw_node;
rcu_read_lock(); - gw_node = rcu_dereference(bat_priv->curr_gw); + gw_node = rcu_dereference(bat_priv->gw.curr_gw); if (!gw_node) goto out;
@@@ -91,23 -91,23 +91,23 @@@ static void batadv_gw_select(struct bat { struct batadv_gw_node *curr_gw_node;
- spin_lock_bh(&bat_priv->gw_list_lock); + spin_lock_bh(&bat_priv->gw.list_lock);
if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) new_gw_node = NULL;
- curr_gw_node = rcu_dereference_protected(bat_priv->curr_gw, 1); - rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); + curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1); + rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node);
if (curr_gw_node) batadv_gw_node_free_ref(curr_gw_node);
- spin_unlock_bh(&bat_priv->gw_list_lock); + spin_unlock_bh(&bat_priv->gw.list_lock); }
void batadv_gw_deselect(struct batadv_priv *bat_priv) { - atomic_set(&bat_priv->gw_reselect, 1); + atomic_set(&bat_priv->gw.reselect, 1); }
static struct batadv_gw_node * @@@ -117,12 -117,17 +117,17 @@@ batadv_gw_get_best_gw_node(struct batad struct hlist_node *node; struct batadv_gw_node *gw_node, *curr_gw = NULL; uint32_t max_gw_factor = 0, tmp_gw_factor = 0; + uint32_t gw_divisor; uint8_t max_tq = 0; int down, up; + uint8_t tq_avg; struct batadv_orig_node *orig_node;
+ gw_divisor = BATADV_TQ_LOCAL_WINDOW_SIZE * BATADV_TQ_LOCAL_WINDOW_SIZE; + gw_divisor *= 64; + rcu_read_lock(); - hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { + hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) { if (gw_node->deleted) continue;
@@@ -134,19 -139,19 +139,19 @@@ if (!atomic_inc_not_zero(&gw_node->refcount)) goto next;
+ tq_avg = router->tq_avg; + switch (atomic_read(&bat_priv->gw_sel_class)) { case 1: /* fast connection */ batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, &down, &up);
- tmp_gw_factor = (router->tq_avg * router->tq_avg * - down * 100 * 100) / - (BATADV_TQ_LOCAL_WINDOW_SIZE * - BATADV_TQ_LOCAL_WINDOW_SIZE * 64); + tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100; + tmp_gw_factor /= gw_divisor;
if ((tmp_gw_factor > max_gw_factor) || ((tmp_gw_factor == max_gw_factor) && - (router->tq_avg > max_tq))) { + (tq_avg > max_tq))) { if (curr_gw) batadv_gw_node_free_ref(curr_gw); curr_gw = gw_node; @@@ -161,7 -166,7 +166,7 @@@ * soon as a better gateway appears which has * $routing_class more tq points) */ - if (router->tq_avg > max_tq) { + if (tq_avg > max_tq) { if (curr_gw) batadv_gw_node_free_ref(curr_gw); curr_gw = gw_node; @@@ -170,8 -175,8 +175,8 @@@ break; }
- if (router->tq_avg > max_tq) - max_tq = router->tq_avg; + if (tq_avg > max_tq) + max_tq = tq_avg;
if (tmp_gw_factor > max_gw_factor) max_gw_factor = tmp_gw_factor; @@@ -200,11 -205,11 +205,11 @@@ void batadv_gw_election(struct batadv_p if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) goto out;
- if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect)) - goto out; - curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
+ if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw) + goto out; + next_gw = batadv_gw_get_best_gw_node(bat_priv);
if (curr_gw == next_gw) @@@ -321,9 -326,9 +326,9 @@@ static void batadv_gw_node_add(struct b gw_node->orig_node = orig_node; atomic_set(&gw_node->refcount, 1);
- spin_lock_bh(&bat_priv->gw_list_lock); - hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list); - spin_unlock_bh(&bat_priv->gw_list_lock); + spin_lock_bh(&bat_priv->gw.list_lock); + hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); + spin_unlock_bh(&bat_priv->gw.list_lock);
batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up); batadv_dbg(BATADV_DBG_BATMAN, bat_priv, @@@ -350,7 -355,7 +355,7 @@@ void batadv_gw_node_update(struct batad curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
rcu_read_lock(); - hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { + hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) { if (gw_node->orig_node != orig_node) continue;
@@@ -404,10 -409,10 +409,10 @@@ void batadv_gw_node_purge(struct batadv
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
- spin_lock_bh(&bat_priv->gw_list_lock); + spin_lock_bh(&bat_priv->gw.list_lock);
hlist_for_each_entry_safe(gw_node, node, node_tmp, - &bat_priv->gw_list, list) { + &bat_priv->gw.list, list) { if (((!gw_node->deleted) || (time_before(jiffies, gw_node->deleted + timeout))) && atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) @@@ -420,7 -425,7 +425,7 @@@ batadv_gw_node_free_ref(gw_node); }
- spin_unlock_bh(&bat_priv->gw_list_lock); + spin_unlock_bh(&bat_priv->gw.list_lock);
/* gw_deselect() needs to acquire the gw_list_lock */ if (do_deselect) @@@ -496,7 -501,7 +501,7 @@@ int batadv_gw_client_seq_print_text(str primary_if->net_dev->dev_addr, net_dev->name);
rcu_read_lock(); - hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { + hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) { if (gw_node->deleted) continue;
diff --combined net/batman-adv/hard-interface.c index 282bf6e,d112fd6..d112fd6 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@@ -103,13 -103,14 +103,14 @@@ static void batadv_primary_if_update_ad { struct batadv_vis_packet *vis_packet; struct batadv_hard_iface *primary_if; + struct sk_buff *skb;
primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out;
- vis_packet = (struct batadv_vis_packet *) - bat_priv->my_vis_info->skb_packet->data; + skb = bat_priv->vis.my_info->skb_packet; + vis_packet = (struct batadv_vis_packet *)skb->data; memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN); @@@ -313,7 -314,13 +314,13 @@@ int batadv_hardif_enable_interface(stru hard_iface->if_num = bat_priv->num_ifaces; bat_priv->num_ifaces++; hard_iface->if_status = BATADV_IF_INACTIVE; - batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces); + ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces); + if (ret < 0) { + bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); + bat_priv->num_ifaces--; + hard_iface->if_status = BATADV_IF_NOT_IN_USE; + goto err_dev; + }
hard_iface->batman_adv_ptype.type = ethertype; hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv; diff --combined net/batman-adv/main.c index 13c88b2,b4aa470..b4aa470 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@@ -58,9 -58,6 +58,6 @@@ static int __init batadv_init(void
batadv_iv_init();
- /* the name should not be longer than 10 chars - see - * http://lwn.net/Articles/23634/ - */ batadv_event_workqueue = create_singlethread_workqueue("bat_events");
if (!batadv_event_workqueue) @@@ -97,20 -94,20 +94,20 @@@ int batadv_mesh_init(struct net_device
spin_lock_init(&bat_priv->forw_bat_list_lock); spin_lock_init(&bat_priv->forw_bcast_list_lock); - spin_lock_init(&bat_priv->tt_changes_list_lock); - spin_lock_init(&bat_priv->tt_req_list_lock); - spin_lock_init(&bat_priv->tt_roam_list_lock); - spin_lock_init(&bat_priv->tt_buff_lock); - spin_lock_init(&bat_priv->gw_list_lock); - spin_lock_init(&bat_priv->vis_hash_lock); - spin_lock_init(&bat_priv->vis_list_lock); + spin_lock_init(&bat_priv->tt.changes_list_lock); + spin_lock_init(&bat_priv->tt.req_list_lock); + spin_lock_init(&bat_priv->tt.roam_list_lock); + spin_lock_init(&bat_priv->tt.last_changeset_lock); + spin_lock_init(&bat_priv->gw.list_lock); + spin_lock_init(&bat_priv->vis.hash_lock); + spin_lock_init(&bat_priv->vis.list_lock);
INIT_HLIST_HEAD(&bat_priv->forw_bat_list); INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); - INIT_HLIST_HEAD(&bat_priv->gw_list); - INIT_LIST_HEAD(&bat_priv->tt_changes_list); - INIT_LIST_HEAD(&bat_priv->tt_req_list); - INIT_LIST_HEAD(&bat_priv->tt_roam_list); + INIT_HLIST_HEAD(&bat_priv->gw.list); + INIT_LIST_HEAD(&bat_priv->tt.changes_list); + INIT_LIST_HEAD(&bat_priv->tt.req_list); + INIT_LIST_HEAD(&bat_priv->tt.roam_list);
ret = batadv_originator_init(bat_priv); if (ret < 0) @@@ -131,7 -128,7 +128,7 @@@ if (ret < 0) goto err;
- atomic_set(&bat_priv->gw_reselect, 0); + atomic_set(&bat_priv->gw.reselect, 0); atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
return 0; diff --combined net/batman-adv/main.h index 5d8fa07,0000000..d57b746 mode 100644,000000..100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@@ -1,280 -1,0 +1,281 @@@ +/* Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef _NET_BATMAN_ADV_MAIN_H_ +#define _NET_BATMAN_ADV_MAIN_H_ + +#define BATADV_DRIVER_AUTHOR "Marek Lindner lindner_marek@yahoo.de, " \ + "Simon Wunderlich siwu@hrz.tu-chemnitz.de" +#define BATADV_DRIVER_DESC "B.A.T.M.A.N. advanced" +#define BATADV_DRIVER_DEVICE "batman-adv" + +#ifndef BATADV_SOURCE_VERSION - #define BATADV_SOURCE_VERSION "2012.3.0" ++#define BATADV_SOURCE_VERSION "2012.4.0" +#endif + +/* B.A.T.M.A.N. parameters */ + +#define BATADV_TQ_MAX_VALUE 255 +#define BATADV_JITTER 20 + +/* Time To Live of broadcast messages */ +#define BATADV_TTL 50 + +/* purge originators after time in seconds if no valid packet comes in + * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE + */ +#define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */ - #define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in miliseconds */ - #define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in miliseconds */ ++#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */ ++#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */ ++#define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */ +/* sliding packet range of received originator messages in sequence numbers + * (should be a multiple of our word size) + */ +#define BATADV_TQ_LOCAL_WINDOW_SIZE 64 - /* miliseconds we have to keep pending tt_req */ ++/* milliseconds we have to keep pending tt_req */ +#define BATADV_TT_REQUEST_TIMEOUT 3000 + +#define BATADV_TQ_GLOBAL_WINDOW_SIZE 5 +#define BATADV_TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 +#define BATADV_TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 +#define BATADV_TQ_TOTAL_BIDRECT_LIMIT 1 + +/* number of OGMs sent with the last tt diff */ +#define BATADV_TT_OGM_APPEND_MAX 3 + +/* Time in which a client can roam at most ROAMING_MAX_COUNT times in - * miliseconds ++ * milliseconds + */ +#define BATADV_ROAMING_MAX_TIME 20000 +#define BATADV_ROAMING_MAX_COUNT 5 + +#define BATADV_NO_FLAGS 0 + +#define BATADV_NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */ + +#define BATADV_NUM_WORDS BITS_TO_LONGS(BATADV_TQ_LOCAL_WINDOW_SIZE) + +#define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ + +#define BATADV_VIS_INTERVAL 5000 /* 5 seconds */ + +/* how much worse secondary interfaces may be to be considered as bonding + * candidates + */ +#define BATADV_BONDING_TQ_THRESHOLD 50 + +/* should not be bigger than 512 bytes or change the size of + * forw_packet->direct_link_flags + */ +#define BATADV_MAX_AGGREGATION_BYTES 512 +#define BATADV_MAX_AGGREGATION_MS 100 + +#define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ +#define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) +#define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) + +#define BATADV_DUPLIST_SIZE 16 +#define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */ +/* don't reset again within 30 seconds */ +#define BATADV_RESET_PROTECTION_MS 30000 +#define BATADV_EXPECTED_SEQNO_RANGE 65536 + +enum batadv_mesh_state { + BATADV_MESH_INACTIVE, + BATADV_MESH_ACTIVE, + BATADV_MESH_DEACTIVATING, +}; + +#define BATADV_BCAST_QUEUE_LEN 256 +#define BATADV_BATMAN_QUEUE_LEN 256 + +enum batadv_uev_action { + BATADV_UEV_ADD = 0, + BATADV_UEV_DEL, + BATADV_UEV_CHANGE, +}; + +enum batadv_uev_type { + BATADV_UEV_GW = 0, +}; + +#define BATADV_GW_THRESHOLD 50 + +/* Debug Messages */ +#ifdef pr_fmt +#undef pr_fmt +#endif +/* Append 'batman-adv: ' before kernel messages */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + - /* all messages related to routing / flooding / broadcasting / etc */ - enum batadv_dbg_level { - BATADV_DBG_BATMAN = 1 << 0, - BATADV_DBG_ROUTES = 1 << 1, /* route added / changed / deleted */ - BATADV_DBG_TT = 1 << 2, /* translation table operations */ - BATADV_DBG_BLA = 1 << 3, /* bridge loop avoidance */ - BATADV_DBG_ALL = 15, - }; - +/* Kernel headers */ + +#include <linux/mutex.h> /* mutex */ +#include <linux/module.h> /* needed by all modules */ +#include <linux/netdevice.h> /* netdevice */ +#include <linux/etherdevice.h> /* ethernet address classification */ +#include <linux/if_ether.h> /* ethernet header */ +#include <linux/poll.h> /* poll_table */ +#include <linux/kthread.h> /* kernel threads */ +#include <linux/pkt_sched.h> /* schedule types */ +#include <linux/workqueue.h> /* workqueue */ +#include <linux/percpu.h> +#include <linux/slab.h> +#include <net/sock.h> /* struct sock */ +#include <linux/jiffies.h> +#include <linux/seq_file.h> +#include "types.h" + +extern char batadv_routing_algo[]; +extern struct list_head batadv_hardif_list; + +extern unsigned char batadv_broadcast_addr[]; +extern struct workqueue_struct *batadv_event_workqueue; + +int batadv_mesh_init(struct net_device *soft_iface); +void batadv_mesh_free(struct net_device *soft_iface); +void batadv_inc_module_count(void); +void batadv_dec_module_count(void); +int batadv_is_my_mac(const uint8_t *addr); +int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *ptype, + struct net_device *orig_dev); +int +batadv_recv_handler_register(uint8_t packet_type, + int (*recv_handler)(struct sk_buff *, + struct batadv_hard_iface *)); +void batadv_recv_handler_unregister(uint8_t packet_type); +int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops); +int batadv_algo_select(struct batadv_priv *bat_priv, char *name); +int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); + ++/* all messages related to routing / flooding / broadcasting / etc */ ++enum batadv_dbg_level { ++ BATADV_DBG_BATMAN = BIT(0), ++ BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */ ++ BATADV_DBG_TT = BIT(2), /* translation table operations */ ++ BATADV_DBG_BLA = BIT(3), /* bridge loop avoidance */ ++ BATADV_DBG_ALL = 15, ++}; ++ +#ifdef CONFIG_BATMAN_ADV_DEBUG +int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) +__printf(2, 3); + +#define batadv_dbg(type, bat_priv, fmt, arg...) \ + do { \ + if (atomic_read(&bat_priv->log_level) & type) \ + batadv_debug_log(bat_priv, fmt, ## arg);\ + } \ + while (0) +#else /* !CONFIG_BATMAN_ADV_DEBUG */ +__printf(3, 4) +static inline void batadv_dbg(int type __always_unused, + struct batadv_priv *bat_priv __always_unused, + const char *fmt __always_unused, ...) +{ +} +#endif + +#define batadv_info(net_dev, fmt, arg...) \ + do { \ + struct net_device *_netdev = (net_dev); \ + struct batadv_priv *_batpriv = netdev_priv(_netdev); \ + batadv_dbg(BATADV_DBG_ALL, _batpriv, fmt, ## arg); \ + pr_info("%s: " fmt, _netdev->name, ## arg); \ + } while (0) +#define batadv_err(net_dev, fmt, arg...) \ + do { \ + struct net_device *_netdev = (net_dev); \ + struct batadv_priv *_batpriv = netdev_priv(_netdev); \ + batadv_dbg(BATADV_DBG_ALL, _batpriv, fmt, ## arg); \ + pr_err("%s: " fmt, _netdev->name, ## arg); \ + } while (0) + +/* returns 1 if they are the same ethernet addr + * + * note: can't use compare_ether_addr() as it requires aligned memory + */ +static inline int batadv_compare_eth(const void *data1, const void *data2) +{ + return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); +} + +/** + * has_timed_out - compares current time (jiffies) and timestamp + timeout + * @timestamp: base value to compare with (in jiffies) + * @timeout: added to base value before comparing (in milliseconds) + * + * Returns true if current time is after timestamp + timeout + */ +static inline bool batadv_has_timed_out(unsigned long timestamp, + unsigned int timeout) +{ + return time_is_before_jiffies(timestamp + msecs_to_jiffies(timeout)); +} + +#define batadv_atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) + +/* Returns the smallest signed integer in two's complement with the sizeof x */ +#define batadv_smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u))) + +/* Checks if a sequence number x is a predecessor/successor of y. + * they handle overflows/underflows and can correctly check for a + * predecessor/successor unless the variable sequence number has grown by + * more then 2**(bitwidth(x)-1)-1. + * This means that for a uint8_t with the maximum value 255, it would think: + * - when adding nothing - it is neither a predecessor nor a successor + * - before adding more than 127 to the starting value - it is a predecessor, + * - when adding 128 - it is neither a predecessor nor a successor, + * - after adding more than 127 to the starting value - it is a successor + */ +#define batadv_seq_before(x, y) ({typeof(x) _d1 = (x); \ + typeof(y) _d2 = (y); \ + typeof(x) _dummy = (_d1 - _d2); \ + (void) (&_d1 == &_d2); \ + _dummy > batadv_smallest_signed_int(_dummy); }) +#define batadv_seq_after(x, y) batadv_seq_before(y, x) + +/* Stop preemption on local cpu while incrementing the counter */ +static inline void batadv_add_counter(struct batadv_priv *bat_priv, size_t idx, + size_t count) +{ + int cpu = get_cpu(); + per_cpu_ptr(bat_priv->bat_counters, cpu)[idx] += count; + put_cpu(); +} + +#define batadv_inc_counter(b, i) batadv_add_counter(b, i, 1) + +/* Sum and return the cpu-local counters for index 'idx' */ +static inline uint64_t batadv_sum_counter(struct batadv_priv *bat_priv, + size_t idx) +{ + uint64_t *counters, sum = 0; + int cpu; + + for_each_possible_cpu(cpu) { + counters = per_cpu_ptr(bat_priv->bat_counters, cpu); + sum += counters[idx]; + } + + return sum; +} + +#endif /* _NET_BATMAN_ADV_MAIN_H_ */ diff --combined net/batman-adv/packet.h index 8d3e55a,2d23a14..2d23a14 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@@ -37,10 -37,10 +37,10 @@@ enum batadv_packettype #define BATADV_COMPAT_VERSION 14
enum batadv_iv_flags { - BATADV_NOT_BEST_NEXT_HOP = 1 << 3, - BATADV_PRIMARIES_FIRST_HOP = 1 << 4, - BATADV_VIS_SERVER = 1 << 5, - BATADV_DIRECTLINK = 1 << 6, + BATADV_NOT_BEST_NEXT_HOP = BIT(3), + BATADV_PRIMARIES_FIRST_HOP = BIT(4), + BATADV_VIS_SERVER = BIT(5), + BATADV_DIRECTLINK = BIT(6), };
/* ICMP message types */ @@@ -60,8 -60,8 +60,8 @@@ enum batadv_vis_packettype
/* fragmentation defines */ enum batadv_unicast_frag_flags { - BATADV_UNI_FRAG_HEAD = 1 << 0, - BATADV_UNI_FRAG_LARGETAIL = 1 << 1, + BATADV_UNI_FRAG_HEAD = BIT(0), + BATADV_UNI_FRAG_LARGETAIL = BIT(1), };
/* TT_QUERY subtypes */ @@@ -74,26 -74,27 +74,27 @@@ enum batadv_tt_query_packettype
/* TT_QUERY flags */ enum batadv_tt_query_flags { - BATADV_TT_FULL_TABLE = 1 << 2, + BATADV_TT_FULL_TABLE = BIT(2), };
/* BATADV_TT_CLIENT flags. - * Flags from 1 to 1 << 7 are sent on the wire, while flags from 1 << 8 to - * 1 << 15 are used for local computation only + * Flags from BIT(0) to BIT(7) are sent on the wire, while flags from BIT(8) to + * BIT(15) are used for local computation only */ enum batadv_tt_client_flags { - BATADV_TT_CLIENT_DEL = 1 << 0, - BATADV_TT_CLIENT_ROAM = 1 << 1, - BATADV_TT_CLIENT_WIFI = 1 << 2, - BATADV_TT_CLIENT_NOPURGE = 1 << 8, - BATADV_TT_CLIENT_NEW = 1 << 9, - BATADV_TT_CLIENT_PENDING = 1 << 10, + BATADV_TT_CLIENT_DEL = BIT(0), + BATADV_TT_CLIENT_ROAM = BIT(1), + BATADV_TT_CLIENT_WIFI = BIT(2), + BATADV_TT_CLIENT_TEMP = BIT(3), + BATADV_TT_CLIENT_NOPURGE = BIT(8), + BATADV_TT_CLIENT_NEW = BIT(9), + BATADV_TT_CLIENT_PENDING = BIT(10), };
/* claim frame types for the bridge loop avoidance */ enum batadv_bla_claimframe { - BATADV_CLAIM_TYPE_ADD = 0x00, - BATADV_CLAIM_TYPE_DEL = 0x01, + BATADV_CLAIM_TYPE_CLAIM = 0x00, + BATADV_CLAIM_TYPE_UNCLAIM = 0x01, BATADV_CLAIM_TYPE_ANNOUNCE = 0x02, BATADV_CLAIM_TYPE_REQUEST = 0x03, }; diff --combined net/batman-adv/routing.c index bc2b88b,939fc01..939fc01 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@@ -579,32 -579,45 +579,45 @@@ batadv_find_ifalter_router(struct batad return router; }
- int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if) + static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size) { - struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); - struct batadv_tt_query_packet *tt_query; - uint16_t tt_size; struct ethhdr *ethhdr; - char tt_flag; - size_t packet_size;
/* drop packet if it has not necessary minimum size */ - if (unlikely(!pskb_may_pull(skb, - sizeof(struct batadv_tt_query_packet)))) - goto out; - - /* I could need to modify it */ - if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0) - goto out; + if (unlikely(!pskb_may_pull(skb, hdr_size))) + return -1;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with unicast indication but broadcast recipient */ if (is_broadcast_ether_addr(ethhdr->h_dest)) - goto out; + return -1;
/* packet with broadcast sender address */ if (is_broadcast_ether_addr(ethhdr->h_source)) + return -1; + + /* not for me */ + if (!batadv_is_my_mac(ethhdr->h_dest)) + return -1; + + return 0; + } + + int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if) + { + struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); + struct batadv_tt_query_packet *tt_query; + uint16_t tt_size; + int hdr_size = sizeof(*tt_query); + char tt_flag; + size_t packet_size; + + if (batadv_check_unicast_packet(skb, hdr_size) < 0) + return NET_RX_DROP; + + /* I could need to modify it */ + if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0) goto out;
tt_query = (struct batadv_tt_query_packet *)skb->data; @@@ -721,7 -734,7 +734,7 @@@ int batadv_recv_roam_adv(struct sk_buf * been incremented yet. This flag will make me check all the incoming * packets for the correct destination. */ - bat_priv->tt_poss_change = true; + bat_priv->tt.poss_change = true;
batadv_orig_node_free_ref(orig_node); out: @@@ -819,31 -832,6 +832,6 @@@ err return NULL; }
- static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size) - { - struct ethhdr *ethhdr; - - /* drop packet if it has not necessary minimum size */ - if (unlikely(!pskb_may_pull(skb, hdr_size))) - return -1; - - ethhdr = (struct ethhdr *)skb_mac_header(skb); - - /* packet with unicast indication but broadcast recipient */ - if (is_broadcast_ether_addr(ethhdr->h_dest)) - return -1; - - /* packet with broadcast sender address */ - if (is_broadcast_ether_addr(ethhdr->h_source)) - return -1; - - /* not for me */ - if (!batadv_is_my_mac(ethhdr->h_dest)) - return -1; - - return 0; - } - static int batadv_route_unicast_packet(struct sk_buff *skb, struct batadv_hard_iface *recv_if) { @@@ -947,8 -935,8 +935,8 @@@ static int batadv_check_unicast_ttvn(st unicast_packet = (struct batadv_unicast_packet *)skb->data;
if (batadv_is_my_mac(unicast_packet->dest)) { - tt_poss_change = bat_priv->tt_poss_change; - curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); + tt_poss_change = bat_priv->tt.poss_change; + curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); } else { orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->dest); @@@ -993,8 -981,7 +981,7 @@@ } else { memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); - curr_ttvn = (uint8_t) - atomic_read(&orig_node->last_ttvn); + curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); batadv_orig_node_free_ref(orig_node); }
@@@ -1025,8 -1012,9 +1012,9 @@@ int batadv_recv_unicast_packet(struct s
/* packet for me */ if (batadv_is_my_mac(unicast_packet->dest)) { - batadv_interface_rx(recv_if->soft_iface, skb, recv_if, - hdr_size); + batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, + NULL); + return NET_RX_SUCCESS; }
@@@ -1063,7 -1051,7 +1051,7 @@@ int batadv_recv_ucast_frag_packet(struc return NET_RX_SUCCESS;
batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, - sizeof(struct batadv_unicast_packet)); + sizeof(struct batadv_unicast_packet), NULL); return NET_RX_SUCCESS; }
@@@ -1150,7 -1138,8 +1138,8 @@@ int batadv_recv_bcast_packet(struct sk_ goto out;
/* broadcast for me */ - batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); + batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, + orig_node); ret = NET_RX_SUCCESS; goto out;
diff --combined net/batman-adv/send.c index 3b4b2da,570a8bc..570a8bc --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@@ -190,13 -190,13 +190,13 @@@ out static void batadv_send_outstanding_bcast_packet(struct work_struct *work) { struct batadv_hard_iface *hard_iface; - struct delayed_work *delayed_work = - container_of(work, struct delayed_work, work); + struct delayed_work *delayed_work; struct batadv_forw_packet *forw_packet; struct sk_buff *skb1; struct net_device *soft_iface; struct batadv_priv *bat_priv;
+ delayed_work = container_of(work, struct delayed_work, work); forw_packet = container_of(delayed_work, struct batadv_forw_packet, delayed_work); soft_iface = forw_packet->if_incoming->soft_iface; @@@ -239,11 -239,11 +239,11 @@@ out
void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work) { - struct delayed_work *delayed_work = - container_of(work, struct delayed_work, work); + struct delayed_work *delayed_work; struct batadv_forw_packet *forw_packet; struct batadv_priv *bat_priv;
+ delayed_work = container_of(work, struct delayed_work, work); forw_packet = container_of(delayed_work, struct batadv_forw_packet, delayed_work); bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); diff --combined net/batman-adv/soft-interface.c index 109ea2a,0000000..7b683e0 mode 100644,000000..100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@@ -1,560 -1,0 +1,583 @@@ +/* Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#include "main.h" +#include "soft-interface.h" +#include "hard-interface.h" +#include "routing.h" +#include "send.h" +#include "debugfs.h" +#include "translation-table.h" +#include "hash.h" +#include "gateway_common.h" +#include "gateway_client.h" +#include "sysfs.h" +#include "originator.h" +#include <linux/slab.h> +#include <linux/ethtool.h> +#include <linux/etherdevice.h> +#include <linux/if_vlan.h> +#include "unicast.h" +#include "bridge_loop_avoidance.h" + + +static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); +static void batadv_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info); +static u32 batadv_get_msglevel(struct net_device *dev); +static void batadv_set_msglevel(struct net_device *dev, u32 value); +static u32 batadv_get_link(struct net_device *dev); +static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data); +static void batadv_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data); +static int batadv_get_sset_count(struct net_device *dev, int stringset); + +static const struct ethtool_ops batadv_ethtool_ops = { + .get_settings = batadv_get_settings, + .get_drvinfo = batadv_get_drvinfo, + .get_msglevel = batadv_get_msglevel, + .set_msglevel = batadv_set_msglevel, + .get_link = batadv_get_link, + .get_strings = batadv_get_strings, + .get_ethtool_stats = batadv_get_ethtool_stats, + .get_sset_count = batadv_get_sset_count, +}; + +int batadv_skb_head_push(struct sk_buff *skb, unsigned int len) +{ + int result; + + /* TODO: We must check if we can release all references to non-payload + * data using skb_header_release in our skbs to allow skb_cow_header to + * work optimally. This means that those skbs are not allowed to read + * or write any data which is before the current position of skb->data + * after that call and thus allow other skbs with the same data buffer + * to write freely in that area. + */ + result = skb_cow_head(skb, len); + if (result < 0) + return result; + + skb_push(skb, len); + return 0; +} + +static int batadv_interface_open(struct net_device *dev) +{ + netif_start_queue(dev); + return 0; +} + +static int batadv_interface_release(struct net_device *dev) +{ + netif_stop_queue(dev); + return 0; +} + +static struct net_device_stats *batadv_interface_stats(struct net_device *dev) +{ + struct batadv_priv *bat_priv = netdev_priv(dev); - return &bat_priv->stats; ++ struct net_device_stats *stats = &bat_priv->stats; ++ ++ stats->tx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_TX); ++ stats->tx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_TX_BYTES); ++ stats->tx_dropped = batadv_sum_counter(bat_priv, BATADV_CNT_TX_DROPPED); ++ stats->rx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_RX); ++ stats->rx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_RX_BYTES); ++ return stats; +} + +static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) +{ + struct batadv_priv *bat_priv = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + /* only modify transtable if it has been initialized before */ + if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { + batadv_tt_local_remove(bat_priv, dev->dev_addr, + "mac address changed", false); + batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX); + } + + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + dev->addr_assign_type &= ~NET_ADDR_RANDOM; + return 0; +} + +static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu) +{ + /* check ranges */ + if ((new_mtu < 68) || (new_mtu > batadv_hardif_min_mtu(dev))) + return -EINVAL; + + dev->mtu = new_mtu; + + return 0; +} + +static int batadv_interface_tx(struct sk_buff *skb, + struct net_device *soft_iface) +{ + struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct batadv_priv *bat_priv = netdev_priv(soft_iface); + struct batadv_hard_iface *primary_if = NULL; + struct batadv_bcast_packet *bcast_packet; + struct vlan_ethhdr *vhdr; + __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN); + static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00, + 0x00}; + unsigned int header_len = 0; + int data_len = skb->len, ret; + short vid __maybe_unused = -1; + bool do_bcast = false; ++ uint32_t seqno; + + if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) + goto dropped; + + soft_iface->trans_start = jiffies; + + switch (ntohs(ethhdr->h_proto)) { + case ETH_P_8021Q: + vhdr = (struct vlan_ethhdr *)skb->data; + vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; + + if (vhdr->h_vlan_encapsulated_proto != ethertype) + break; + + /* fall through */ + case BATADV_ETH_P_BATMAN: + goto dropped; + } + + if (batadv_bla_tx(bat_priv, skb, vid)) + goto dropped; + + /* Register the client MAC in the transtable */ + batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); + + /* don't accept stp packets. STP does not help in meshes. + * better use the bridge loop avoidance ... + */ + if (batadv_compare_eth(ethhdr->h_dest, stp_addr)) + goto dropped; + + if (is_multicast_ether_addr(ethhdr->h_dest)) { + do_bcast = true; + + switch (atomic_read(&bat_priv->gw_mode)) { + case BATADV_GW_MODE_SERVER: + /* gateway servers should not send dhcp + * requests into the mesh + */ + ret = batadv_gw_is_dhcp_target(skb, &header_len); + if (ret) + goto dropped; + break; + case BATADV_GW_MODE_CLIENT: + /* gateway clients should send dhcp requests + * via unicast to their gateway + */ + ret = batadv_gw_is_dhcp_target(skb, &header_len); + if (ret) + do_bcast = false; + break; + case BATADV_GW_MODE_OFF: + default: + break; + } + } + + /* ethernet packet should be broadcasted */ + if (do_bcast) { + primary_if = batadv_primary_if_get_selected(bat_priv); + if (!primary_if) + goto dropped; + + if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) + goto dropped; + + bcast_packet = (struct batadv_bcast_packet *)skb->data; + bcast_packet->header.version = BATADV_COMPAT_VERSION; + bcast_packet->header.ttl = BATADV_TTL; + + /* batman packet type: broadcast */ + bcast_packet->header.packet_type = BATADV_BCAST; + bcast_packet->reserved = 0; + + /* hw address of first interface is the orig mac because only + * this mac is known throughout the mesh + */ + memcpy(bcast_packet->orig, + primary_if->net_dev->dev_addr, ETH_ALEN); + + /* set broadcast sequence number */ - bcast_packet->seqno = - htonl(atomic_inc_return(&bat_priv->bcast_seqno)); ++ seqno = atomic_inc_return(&bat_priv->bcast_seqno); ++ bcast_packet->seqno = htonl(seqno); + + batadv_add_bcast_packet_to_list(bat_priv, skb, 1); + + /* a copy is stored in the bcast list, therefore removing + * the original skb. + */ + kfree_skb(skb); + + /* unicast packet */ + } else { + if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) { + ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr); + if (ret) + goto dropped; + } + + ret = batadv_unicast_send_skb(skb, bat_priv); + if (ret != 0) + goto dropped_freed; + } + - bat_priv->stats.tx_packets++; - bat_priv->stats.tx_bytes += data_len; ++ batadv_inc_counter(bat_priv, BATADV_CNT_TX); ++ batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len); + goto end; + +dropped: + kfree_skb(skb); +dropped_freed: - bat_priv->stats.tx_dropped++; ++ batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED); +end: + if (primary_if) + batadv_hardif_free_ref(primary_if); + return NETDEV_TX_OK; +} + +void batadv_interface_rx(struct net_device *soft_iface, + struct sk_buff *skb, struct batadv_hard_iface *recv_if, - int hdr_size) ++ int hdr_size, struct batadv_orig_node *orig_node) +{ + struct batadv_priv *bat_priv = netdev_priv(soft_iface); + struct ethhdr *ethhdr; + struct vlan_ethhdr *vhdr; + struct batadv_header *batadv_header = (struct batadv_header *)skb->data; + short vid __maybe_unused = -1; + __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN); + bool is_bcast; + + is_bcast = (batadv_header->packet_type == BATADV_BCAST); + + /* check if enough space is available for pulling, and pull */ + if (!pskb_may_pull(skb, hdr_size)) + goto dropped; + + skb_pull_rcsum(skb, hdr_size); + skb_reset_mac_header(skb); + + ethhdr = (struct ethhdr *)skb_mac_header(skb); + + switch (ntohs(ethhdr->h_proto)) { + case ETH_P_8021Q: + vhdr = (struct vlan_ethhdr *)skb->data; + vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; + + if (vhdr->h_vlan_encapsulated_proto != ethertype) + break; + + /* fall through */ + case BATADV_ETH_P_BATMAN: + goto dropped; + } + + /* skb->dev & skb->pkt_type are set here */ + if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) + goto dropped; + skb->protocol = eth_type_trans(skb, soft_iface); + + /* should not be necessary anymore as we use skb_pull_rcsum() + * TODO: please verify this and remove this TODO + * -- Dec 21st 2009, Simon Wunderlich + */ + + /* skb->ip_summed = CHECKSUM_UNNECESSARY; */ + - bat_priv->stats.rx_packets++; - bat_priv->stats.rx_bytes += skb->len + ETH_HLEN; ++ batadv_inc_counter(bat_priv, BATADV_CNT_RX); ++ batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, ++ skb->len + ETH_HLEN); + + soft_iface->last_rx = jiffies; + ++ if (orig_node) ++ batadv_tt_add_temporary_global_entry(bat_priv, orig_node, ++ ethhdr->h_source); ++ + if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) + goto dropped; + + /* Let the bridge loop avoidance check the packet. If will + * not handle it, we can safely push it up. + */ + if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) + goto out; + + netif_rx(skb); + goto out; + +dropped: + kfree_skb(skb); +out: + return; +} + +static const struct net_device_ops batadv_netdev_ops = { + .ndo_open = batadv_interface_open, + .ndo_stop = batadv_interface_release, + .ndo_get_stats = batadv_interface_stats, + .ndo_set_mac_address = batadv_interface_set_mac_addr, + .ndo_change_mtu = batadv_interface_change_mtu, + .ndo_start_xmit = batadv_interface_tx, + .ndo_validate_addr = eth_validate_addr +}; + +static void batadv_interface_setup(struct net_device *dev) +{ + struct batadv_priv *priv = netdev_priv(dev); + + ether_setup(dev); + + dev->netdev_ops = &batadv_netdev_ops; + dev->destructor = free_netdev; + dev->tx_queue_len = 0; + + /* can't call min_mtu, because the needed variables + * have not been initialized yet + */ + dev->mtu = ETH_DATA_LEN; + /* reserve more space in the skbuff for our header */ + dev->hard_header_len = BATADV_HEADER_LEN; + + /* generate random address */ + eth_hw_addr_random(dev); + + SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops); + + memset(priv, 0, sizeof(*priv)); +} + +struct net_device *batadv_softif_create(const char *name) +{ + struct net_device *soft_iface; + struct batadv_priv *bat_priv; + int ret; + size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM; + + soft_iface = alloc_netdev(sizeof(*bat_priv), name, + batadv_interface_setup); + + if (!soft_iface) + goto out; + ++ bat_priv = netdev_priv(soft_iface); ++ ++ /* batadv_interface_stats() needs to be available as soon as ++ * register_netdevice() has been called ++ */ ++ bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); ++ if (!bat_priv->bat_counters) ++ goto free_soft_iface; ++ + ret = register_netdevice(soft_iface); + if (ret < 0) { + pr_err("Unable to register the batman interface '%s': %i\n", + name, ret); - goto free_soft_iface; ++ goto free_bat_counters; + } + - bat_priv = netdev_priv(soft_iface); - + atomic_set(&bat_priv->aggregated_ogms, 1); + atomic_set(&bat_priv->bonding, 0); + atomic_set(&bat_priv->bridge_loop_avoidance, 0); + atomic_set(&bat_priv->ap_isolation, 0); + atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE); + atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); + atomic_set(&bat_priv->gw_sel_class, 20); + atomic_set(&bat_priv->gw_bandwidth, 41); + atomic_set(&bat_priv->orig_interval, 1000); + atomic_set(&bat_priv->hop_penalty, 30); + atomic_set(&bat_priv->log_level, 0); + atomic_set(&bat_priv->fragmentation, 1); + atomic_set(&bat_priv->bcast_queue_left, BATADV_BCAST_QUEUE_LEN); + atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN); + + atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); + atomic_set(&bat_priv->bcast_seqno, 1); - atomic_set(&bat_priv->ttvn, 0); - atomic_set(&bat_priv->tt_local_changes, 0); - atomic_set(&bat_priv->tt_ogm_append_cnt, 0); - atomic_set(&bat_priv->bla_num_requests, 0); - - bat_priv->tt_buff = NULL; - bat_priv->tt_buff_len = 0; - bat_priv->tt_poss_change = false; ++ atomic_set(&bat_priv->tt.vn, 0); ++ atomic_set(&bat_priv->tt.local_changes, 0); ++ atomic_set(&bat_priv->tt.ogm_append_cnt, 0); ++#ifdef CONFIG_BATMAN_ADV_BLA ++ atomic_set(&bat_priv->bla.num_requests, 0); ++#endif ++ bat_priv->tt.last_changeset = NULL; ++ bat_priv->tt.last_changeset_len = 0; ++ bat_priv->tt.poss_change = false; + + bat_priv->primary_if = NULL; + bat_priv->num_ifaces = 0; + - bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); - if (!bat_priv->bat_counters) - goto unreg_soft_iface; - + ret = batadv_algo_select(bat_priv, batadv_routing_algo); + if (ret < 0) - goto free_bat_counters; ++ goto unreg_soft_iface; + + ret = batadv_sysfs_add_meshif(soft_iface); + if (ret < 0) - goto free_bat_counters; ++ goto unreg_soft_iface; + + ret = batadv_debugfs_add_meshif(soft_iface); + if (ret < 0) + goto unreg_sysfs; + + ret = batadv_mesh_init(soft_iface); + if (ret < 0) + goto unreg_debugfs; + + return soft_iface; + +unreg_debugfs: + batadv_debugfs_del_meshif(soft_iface); +unreg_sysfs: + batadv_sysfs_del_meshif(soft_iface); - free_bat_counters: - free_percpu(bat_priv->bat_counters); +unreg_soft_iface: ++ free_percpu(bat_priv->bat_counters); + unregister_netdevice(soft_iface); + return NULL; + ++free_bat_counters: ++ free_percpu(bat_priv->bat_counters); +free_soft_iface: + free_netdev(soft_iface); +out: + return NULL; +} + +void batadv_softif_destroy(struct net_device *soft_iface) +{ + batadv_debugfs_del_meshif(soft_iface); + batadv_sysfs_del_meshif(soft_iface); + batadv_mesh_free(soft_iface); + unregister_netdevice(soft_iface); +} + +int batadv_softif_is_valid(const struct net_device *net_dev) +{ + if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx) + return 1; + + return 0; +} + +/* ethtool */ +static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + cmd->supported = 0; + cmd->advertising = 0; + ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + + return 0; +} + +static void batadv_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, "B.A.T.M.A.N. advanced"); + strcpy(info->version, BATADV_SOURCE_VERSION); + strcpy(info->fw_version, "N/A"); + strcpy(info->bus_info, "batman"); +} + +static u32 batadv_get_msglevel(struct net_device *dev) +{ + return -EOPNOTSUPP; +} + +static void batadv_set_msglevel(struct net_device *dev, u32 value) +{ +} + +static u32 batadv_get_link(struct net_device *dev) +{ + return 1; +} + +/* Inspired by drivers/net/ethernet/dlink/sundance.c:1702 + * Declare each description string in struct.name[] to get fixed sized buffer + * and compile time checking for strings longer than ETH_GSTRING_LEN. + */ +static const struct { + const char name[ETH_GSTRING_LEN]; +} batadv_counters_strings[] = { ++ { "tx" }, ++ { "tx_bytes" }, ++ { "tx_dropped" }, ++ { "rx" }, ++ { "rx_bytes" }, + { "forward" }, + { "forward_bytes" }, + { "mgmt_tx" }, + { "mgmt_tx_bytes" }, + { "mgmt_rx" }, + { "mgmt_rx_bytes" }, + { "tt_request_tx" }, + { "tt_request_rx" }, + { "tt_response_tx" }, + { "tt_response_rx" }, + { "tt_roam_adv_tx" }, + { "tt_roam_adv_rx" }, +}; + +static void batadv_get_strings(struct net_device *dev, uint32_t stringset, + uint8_t *data) +{ + if (stringset == ETH_SS_STATS) + memcpy(data, batadv_counters_strings, + sizeof(batadv_counters_strings)); +} + +static void batadv_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, + uint64_t *data) +{ + struct batadv_priv *bat_priv = netdev_priv(dev); + int i; + + for (i = 0; i < BATADV_CNT_NUM; i++) + data[i] = batadv_sum_counter(bat_priv, i); +} + +static int batadv_get_sset_count(struct net_device *dev, int stringset) +{ + if (stringset == ETH_SS_STATS) + return BATADV_CNT_NUM; + + return -EOPNOTSUPP; +} diff --combined net/batman-adv/soft-interface.h index 852c683,07a08fe..07a08fe --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h @@@ -21,8 -21,9 +21,9 @@@ #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
int batadv_skb_head_push(struct sk_buff *skb, unsigned int len); - void batadv_interface_rx(struct net_device *soft_iface, struct sk_buff *skb, - struct batadv_hard_iface *recv_if, int hdr_size); + void batadv_interface_rx(struct net_device *soft_iface, + struct sk_buff *skb, struct batadv_hard_iface *recv_if, + int hdr_size, struct batadv_orig_node *orig_node); struct net_device *batadv_softif_create(const char *name); void batadv_softif_destroy(struct net_device *soft_iface); int batadv_softif_is_valid(const struct net_device *net_dev); diff --combined net/batman-adv/translation-table.c index a438f4b,112edd3..112edd3 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@@ -34,6 -34,10 +34,10 @@@ static void batadv_send_roam_adv(struc static void batadv_tt_purge(struct work_struct *work); static void batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry); + static void batadv_tt_global_del(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig_node, + const unsigned char *addr, + const char *message, bool roaming);
/* returns 1 if they are the same mac addr */ static int batadv_compare_tt(const struct hlist_node *node, const void *data2) @@@ -46,8 -50,8 +50,8 @@@
static void batadv_tt_start_timer(struct batadv_priv *bat_priv) { - INIT_DELAYED_WORK(&bat_priv->tt_work, batadv_tt_purge); - queue_delayed_work(batadv_event_workqueue, &bat_priv->tt_work, + INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); + queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, msecs_to_jiffies(5000)); }
@@@ -88,7 -92,7 +92,7 @@@ batadv_tt_local_hash_find(struct batadv struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_local_entry *tt_local_entry = NULL;
- tt_common_entry = batadv_tt_hash_find(bat_priv->tt_local_hash, data); + tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data); if (tt_common_entry) tt_local_entry = container_of(tt_common_entry, struct batadv_tt_local_entry, @@@ -102,7 -106,7 +106,7 @@@ batadv_tt_global_hash_find(struct batad struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_global_entry *tt_global_entry = NULL;
- tt_common_entry = batadv_tt_hash_find(bat_priv->tt_global_hash, data); + tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data); if (tt_common_entry) tt_global_entry = container_of(tt_common_entry, struct batadv_tt_global_entry, @@@ -152,6 -156,8 +156,8 @@@ static void batadv_tt_orig_list_entry_f static void batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) { + if (!atomic_dec_and_test(&orig_entry->refcount)) + return; /* to avoid race conditions, immediately decrease the tt counter */ atomic_dec(&orig_entry->orig_node->tt_size); call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); @@@ -175,8 -181,8 +181,8 @@@ static void batadv_tt_local_event(struc del_op_requested = flags & BATADV_TT_CLIENT_DEL;
/* check for ADD+DEL or DEL+ADD events */ - spin_lock_bh(&bat_priv->tt_changes_list_lock); - list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, + spin_lock_bh(&bat_priv->tt.changes_list_lock); + list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, list) { if (!batadv_compare_eth(entry->change.addr, addr)) continue; @@@ -197,20 -203,21 +203,21 @@@ del: list_del(&entry->list); kfree(entry); + kfree(tt_change_node); event_removed = true; goto unlock; }
/* track the change in the OGMinterval list */ - list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list); + list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
unlock: - spin_unlock_bh(&bat_priv->tt_changes_list_lock); + spin_unlock_bh(&bat_priv->tt.changes_list_lock);
if (event_removed) - atomic_dec(&bat_priv->tt_local_changes); + atomic_dec(&bat_priv->tt.local_changes); else - atomic_inc(&bat_priv->tt_local_changes); + atomic_inc(&bat_priv->tt.local_changes); }
int batadv_tt_len(int changes_num) @@@ -220,12 -227,12 +227,12 @@@
static int batadv_tt_local_init(struct batadv_priv *bat_priv) { - if (bat_priv->tt_local_hash) + if (bat_priv->tt.local_hash) return 0;
- bat_priv->tt_local_hash = batadv_hash_new(1024); + bat_priv->tt.local_hash = batadv_hash_new(1024);
- if (!bat_priv->tt_local_hash) + if (!bat_priv->tt.local_hash) return -ENOMEM;
return 0; @@@ -257,7 -264,7 +264,7 @@@ void batadv_tt_local_add(struct net_dev
batadv_dbg(BATADV_DBG_TT, bat_priv, "Creating new local tt entry: %pM (ttvn: %d)\n", addr, - (uint8_t)atomic_read(&bat_priv->ttvn)); + (uint8_t)atomic_read(&bat_priv->tt.vn));
memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); tt_local_entry->common.flags = BATADV_NO_FLAGS; @@@ -265,6 -272,7 +272,7 @@@ tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; atomic_set(&tt_local_entry->common.refcount, 2); tt_local_entry->last_seen = jiffies; + tt_local_entry->common.added_at = tt_local_entry->last_seen;
/* the batman interface mac address should never be purged */ if (batadv_compare_eth(addr, soft_iface->dev_addr)) @@@ -276,7 -284,7 +284,7 @@@ */ tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
- hash_added = batadv_hash_add(bat_priv->tt_local_hash, batadv_compare_tt, + hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, batadv_choose_orig, &tt_local_entry->common, &tt_local_entry->common.hash_entry); @@@ -347,7 -355,7 +355,7 @@@ static void batadv_tt_prepare_packet_bu primary_if = batadv_primary_if_get_selected(bat_priv);
req_len = min_packet_len; - req_len += batadv_tt_len(atomic_read(&bat_priv->tt_local_changes)); + req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
/* if we have too many changes for one packet don't send any * and wait for the tt table request which will be fragmented @@@ -380,10 -388,10 +388,10 @@@ static int batadv_tt_changes_fill_buff( if (new_len > 0) tot_changes = new_len / batadv_tt_len(1);
- spin_lock_bh(&bat_priv->tt_changes_list_lock); - atomic_set(&bat_priv->tt_local_changes, 0); + spin_lock_bh(&bat_priv->tt.changes_list_lock); + atomic_set(&bat_priv->tt.local_changes, 0);
- list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, + list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, list) { if (count < tot_changes) { memcpy(tt_buff + batadv_tt_len(count), @@@ -393,25 -401,25 +401,25 @@@ list_del(&entry->list); kfree(entry); } - spin_unlock_bh(&bat_priv->tt_changes_list_lock); + spin_unlock_bh(&bat_priv->tt.changes_list_lock);
/* Keep the buffer for possible tt_request */ - spin_lock_bh(&bat_priv->tt_buff_lock); - kfree(bat_priv->tt_buff); - bat_priv->tt_buff_len = 0; - bat_priv->tt_buff = NULL; + spin_lock_bh(&bat_priv->tt.last_changeset_lock); + kfree(bat_priv->tt.last_changeset); + bat_priv->tt.last_changeset_len = 0; + bat_priv->tt.last_changeset = NULL; /* check whether this new OGM has no changes due to size problems */ if (new_len > 0) { /* if kmalloc() fails we will reply with the full table * instead of providing the diff */ - bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC); - if (bat_priv->tt_buff) { - memcpy(bat_priv->tt_buff, tt_buff, new_len); - bat_priv->tt_buff_len = new_len; + bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC); + if (bat_priv->tt.last_changeset) { + memcpy(bat_priv->tt.last_changeset, tt_buff, new_len); + bat_priv->tt.last_changeset_len = new_len; } } - spin_unlock_bh(&bat_priv->tt_buff_lock); + spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
return count; } @@@ -420,7 -428,7 +428,7 @@@ int batadv_tt_local_seq_print_text(stru { struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_priv *bat_priv = netdev_priv(net_dev); - struct batadv_hashtable *hash = bat_priv->tt_local_hash; + struct batadv_hashtable *hash = bat_priv->tt.local_hash; struct batadv_tt_common_entry *tt_common_entry; struct batadv_hard_iface *primary_if; struct hlist_node *node; @@@ -445,7 -453,7 +453,7 @@@
seq_printf(seq, "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", - net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn)); + net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@@ -543,7 -551,7 +551,7 @@@ static void batadv_tt_local_purge_list(
static void batadv_tt_local_purge(struct batadv_priv *bat_priv) { - struct batadv_hashtable *hash = bat_priv->tt_local_hash; + struct batadv_hashtable *hash = bat_priv->tt.local_hash; struct hlist_head *head; spinlock_t *list_lock; /* protects write access to the hash lists */ uint32_t i; @@@ -569,10 -577,10 +577,10 @@@ static void batadv_tt_local_table_free( struct hlist_head *head; uint32_t i;
- if (!bat_priv->tt_local_hash) + if (!bat_priv->tt.local_hash) return;
- hash = bat_priv->tt_local_hash; + hash = bat_priv->tt.local_hash;
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@@ -592,17 -600,17 +600,17 @@@
batadv_hash_destroy(hash);
- bat_priv->tt_local_hash = NULL; + bat_priv->tt.local_hash = NULL; }
static int batadv_tt_global_init(struct batadv_priv *bat_priv) { - if (bat_priv->tt_global_hash) + if (bat_priv->tt.global_hash) return 0;
- bat_priv->tt_global_hash = batadv_hash_new(1024); + bat_priv->tt.global_hash = batadv_hash_new(1024);
- if (!bat_priv->tt_global_hash) + if (!bat_priv->tt.global_hash) return -ENOMEM;
return 0; @@@ -612,62 -620,99 +620,99 @@@ static void batadv_tt_changes_list_free { struct batadv_tt_change_node *entry, *safe;
- spin_lock_bh(&bat_priv->tt_changes_list_lock); + spin_lock_bh(&bat_priv->tt.changes_list_lock);
- list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, + list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, list) { list_del(&entry->list); kfree(entry); }
- atomic_set(&bat_priv->tt_local_changes, 0); - spin_unlock_bh(&bat_priv->tt_changes_list_lock); + atomic_set(&bat_priv->tt.local_changes, 0); + spin_unlock_bh(&bat_priv->tt.changes_list_lock); }
- /* find out if an orig_node is already in the list of a tt_global_entry. - * returns 1 if found, 0 otherwise + /* retrieves the orig_tt_list_entry belonging to orig_node from the + * batadv_tt_global_entry list + * + * returns it with an increased refcounter, NULL if not found */ - static bool - batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, - const struct batadv_orig_node *orig_node) + static struct batadv_tt_orig_list_entry * + batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, + const struct batadv_orig_node *orig_node) { - struct batadv_tt_orig_list_entry *tmp_orig_entry; + struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL; const struct hlist_head *head; struct hlist_node *node; - bool found = false;
rcu_read_lock(); head = &entry->orig_list; hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) { - if (tmp_orig_entry->orig_node == orig_node) { - found = true; - break; - } + if (tmp_orig_entry->orig_node != orig_node) + continue; + if (!atomic_inc_not_zero(&tmp_orig_entry->refcount)) + continue; + + orig_entry = tmp_orig_entry; + break; } rcu_read_unlock(); + + return orig_entry; + } + + /* find out if an orig_node is already in the list of a tt_global_entry. + * returns true if found, false otherwise + */ + static bool + batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, + const struct batadv_orig_node *orig_node) + { + struct batadv_tt_orig_list_entry *orig_entry; + bool found = false; + + orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node); + if (orig_entry) { + found = true; + batadv_tt_orig_list_entry_free_ref(orig_entry); + } + return found; }
static void - batadv_tt_global_add_orig_entry(struct batadv_tt_global_entry *tt_global_entry, + batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, struct batadv_orig_node *orig_node, int ttvn) { struct batadv_tt_orig_list_entry *orig_entry;
+ orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node); + if (orig_entry) { + /* refresh the ttvn: the current value could be a bogus one that + * was added during a "temporary client detection" + */ + orig_entry->ttvn = ttvn; + goto out; + } + orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); if (!orig_entry) - return; + goto out;
INIT_HLIST_NODE(&orig_entry->list); atomic_inc(&orig_node->refcount); atomic_inc(&orig_node->tt_size); orig_entry->orig_node = orig_node; orig_entry->ttvn = ttvn; + atomic_set(&orig_entry->refcount, 2);
- spin_lock_bh(&tt_global_entry->list_lock); + spin_lock_bh(&tt_global->list_lock); hlist_add_head_rcu(&orig_entry->list, - &tt_global_entry->orig_list); - spin_unlock_bh(&tt_global_entry->list_lock); + &tt_global->orig_list); + spin_unlock_bh(&tt_global->list_lock); + out: + if (orig_entry) + batadv_tt_orig_list_entry_free_ref(orig_entry); }
/* caller must hold orig_node refcount */ @@@ -694,11 -739,12 +739,12 @@@ int batadv_tt_global_add(struct batadv_ common->flags = flags; tt_global_entry->roam_at = 0; atomic_set(&common->refcount, 2); + common->added_at = jiffies;
INIT_HLIST_HEAD(&tt_global_entry->orig_list); spin_lock_init(&tt_global_entry->list_lock);
- hash_added = batadv_hash_add(bat_priv->tt_global_hash, + hash_added = batadv_hash_add(bat_priv->tt.global_hash, batadv_compare_tt, batadv_choose_orig, common, &common->hash_entry); @@@ -708,11 -754,20 +754,20 @@@ batadv_tt_global_entry_free_ref(tt_global_entry); goto out_remove; } - - batadv_tt_global_add_orig_entry(tt_global_entry, orig_node, - ttvn); } else { - /* there is already a global entry, use this one. */ + /* If there is already a global entry, we can use this one for + * our processing. + * But if we are trying to add a temporary client we can exit + * directly because the temporary information should never + * override any already known client state (whatever it is) + */ + if (flags & BATADV_TT_CLIENT_TEMP) + goto out; + + /* if the client was temporary added before receiving the first + * OGM announcing it, we have to clear the TEMP flag + */ + tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only * one originator left in the list and we previously received a @@@ -726,12 -781,9 +781,9 @@@ tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; tt_global_entry->roam_at = 0; } - - if (!batadv_tt_global_entry_has_orig(tt_global_entry, - orig_node)) - batadv_tt_global_add_orig_entry(tt_global_entry, - orig_node, ttvn); } + /* add the new orig_entry (if needed) or update it */ + batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
batadv_dbg(BATADV_DBG_TT, bat_priv, "Creating new global tt entry: %pM (via %pM)\n", @@@ -770,11 -822,12 +822,12 @@@ batadv_tt_global_print_entry(struct bat hlist_for_each_entry_rcu(orig_entry, node, head, list) { flags = tt_common_entry->flags; last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); - seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c]\n", + seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c%c]\n", tt_global_entry->common.addr, orig_entry->ttvn, orig_entry->orig_node->orig, last_ttvn, (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), - (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.')); + (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), + (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); } }
@@@ -782,7 -835,7 +835,7 @@@ int batadv_tt_global_seq_print_text(str { struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_priv *bat_priv = netdev_priv(net_dev); - struct batadv_hashtable *hash = bat_priv->tt_global_hash; + struct batadv_hashtable *hash = bat_priv->tt.global_hash; struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_global_entry *tt_global; struct batadv_hard_iface *primary_if; @@@ -883,7 -936,7 +936,7 @@@ batadv_tt_global_del_struct(struct bata "Deleting global tt entry %pM: %s\n", tt_global_entry->common.addr, message);
- batadv_hash_remove(bat_priv->tt_global_hash, batadv_compare_tt, + batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, batadv_choose_orig, tt_global_entry->common.addr); batadv_tt_global_entry_free_ref(tt_global_entry);
@@@ -994,7 -1047,7 +1047,7 @@@ void batadv_tt_global_del_orig(struct b struct batadv_tt_global_entry *tt_global; struct batadv_tt_common_entry *tt_common_entry; uint32_t i; - struct batadv_hashtable *hash = bat_priv->tt_global_hash; + struct batadv_hashtable *hash = bat_priv->tt.global_hash; struct hlist_node *node, *safe; struct hlist_head *head; spinlock_t *list_lock; /* protects write access to the hash lists */ @@@ -1029,49 -1082,63 +1082,63 @@@ orig_node->tt_initialised = false; }
- static void batadv_tt_global_roam_purge_list(struct batadv_priv *bat_priv, - struct hlist_head *head) + static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global, + char **msg) { - struct batadv_tt_common_entry *tt_common_entry; - struct batadv_tt_global_entry *tt_global_entry; - struct hlist_node *node, *node_tmp; - - hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head, - hash_entry) { - tt_global_entry = container_of(tt_common_entry, - struct batadv_tt_global_entry, - common); - if (!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM)) - continue; - if (!batadv_has_timed_out(tt_global_entry->roam_at, - BATADV_TT_CLIENT_ROAM_TIMEOUT)) - continue; + bool purge = false; + unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT; + unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
- batadv_dbg(BATADV_DBG_TT, bat_priv, - "Deleting global tt entry (%pM): Roaming timeout\n", - tt_global_entry->common.addr); + if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) && + batadv_has_timed_out(tt_global->roam_at, roam_timeout)) { + purge = true; + *msg = "Roaming timeout\n"; + }
- hlist_del_rcu(node); - batadv_tt_global_entry_free_ref(tt_global_entry); + if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) && + batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) { + purge = true; + *msg = "Temporary client timeout\n"; } + + return purge; }
- static void batadv_tt_global_roam_purge(struct batadv_priv *bat_priv) + static void batadv_tt_global_purge(struct batadv_priv *bat_priv) { - struct batadv_hashtable *hash = bat_priv->tt_global_hash; + struct batadv_hashtable *hash = bat_priv->tt.global_hash; struct hlist_head *head; + struct hlist_node *node, *node_tmp; spinlock_t *list_lock; /* protects write access to the hash lists */ uint32_t i; + char *msg = NULL; + struct batadv_tt_common_entry *tt_common; + struct batadv_tt_global_entry *tt_global;
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; list_lock = &hash->list_locks[i];
spin_lock_bh(list_lock); - batadv_tt_global_roam_purge_list(bat_priv, head); + hlist_for_each_entry_safe(tt_common, node, node_tmp, head, + hash_entry) { + tt_global = container_of(tt_common, + struct batadv_tt_global_entry, + common); + + if (!batadv_tt_global_to_purge(tt_global, &msg)) + continue; + + batadv_dbg(BATADV_DBG_TT, bat_priv, + "Deleting global tt entry (%pM): %s\n", + tt_global->common.addr, msg); + + hlist_del_rcu(node); + + batadv_tt_global_entry_free_ref(tt_global); + } spin_unlock_bh(list_lock); } - }
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) @@@ -1084,10 -1151,10 +1151,10 @@@ struct hlist_head *head; uint32_t i;
- if (!bat_priv->tt_global_hash) + if (!bat_priv->tt.global_hash) return;
- hash = bat_priv->tt_global_hash; + hash = bat_priv->tt.global_hash;
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@@ -1107,7 -1174,7 +1174,7 @@@
batadv_hash_destroy(hash);
- bat_priv->tt_global_hash = NULL; + bat_priv->tt.global_hash = NULL; }
static bool @@@ -1186,7 -1253,7 +1253,7 @@@ static uint16_t batadv_tt_global_crc(st struct batadv_orig_node *orig_node) { uint16_t total = 0, total_one; - struct batadv_hashtable *hash = bat_priv->tt_global_hash; + struct batadv_hashtable *hash = bat_priv->tt.global_hash; struct batadv_tt_common_entry *tt_common; struct batadv_tt_global_entry *tt_global; struct hlist_node *node; @@@ -1209,6 -1276,12 +1276,12 @@@ */ if (tt_common->flags & BATADV_TT_CLIENT_ROAM) continue; + /* Temporary clients have not been announced yet, so + * they have to be skipped while computing the global + * crc + */ + if (tt_common->flags & BATADV_TT_CLIENT_TEMP) + continue;
/* find out if this global entry is announced by this * originator @@@ -1233,7 -1306,7 +1306,7 @@@ static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) { uint16_t total = 0, total_one; - struct batadv_hashtable *hash = bat_priv->tt_local_hash; + struct batadv_hashtable *hash = bat_priv->tt.local_hash; struct batadv_tt_common_entry *tt_common; struct hlist_node *node; struct hlist_head *head; @@@ -1266,14 -1339,14 +1339,14 @@@ static void batadv_tt_req_list_free(str { struct batadv_tt_req_node *node, *safe;
- spin_lock_bh(&bat_priv->tt_req_list_lock); + spin_lock_bh(&bat_priv->tt.req_list_lock);
- list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { + list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { list_del(&node->list); kfree(node); }
- spin_unlock_bh(&bat_priv->tt_req_list_lock); + spin_unlock_bh(&bat_priv->tt.req_list_lock); }
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, @@@ -1303,15 -1376,15 +1376,15 @@@ static void batadv_tt_req_purge(struct { struct batadv_tt_req_node *node, *safe;
- spin_lock_bh(&bat_priv->tt_req_list_lock); - list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { + spin_lock_bh(&bat_priv->tt.req_list_lock); + list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { if (batadv_has_timed_out(node->issued_at, BATADV_TT_REQUEST_TIMEOUT)) { list_del(&node->list); kfree(node); } } - spin_unlock_bh(&bat_priv->tt_req_list_lock); + spin_unlock_bh(&bat_priv->tt.req_list_lock); }
/* returns the pointer to the new tt_req_node struct if no request @@@ -1323,8 -1396,8 +1396,8 @@@ batadv_new_tt_req_node(struct batadv_pr { struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
- spin_lock_bh(&bat_priv->tt_req_list_lock); - list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) { + spin_lock_bh(&bat_priv->tt.req_list_lock); + list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) { if (batadv_compare_eth(tt_req_node_tmp, orig_node) && !batadv_has_timed_out(tt_req_node_tmp->issued_at, BATADV_TT_REQUEST_TIMEOUT)) @@@ -1338,9 -1411,9 +1411,9 @@@ memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); tt_req_node->issued_at = jiffies;
- list_add(&tt_req_node->list, &bat_priv->tt_req_list); + list_add(&tt_req_node->list, &bat_priv->tt.req_list); unlock: - spin_unlock_bh(&bat_priv->tt_req_list_lock); + spin_unlock_bh(&bat_priv->tt.req_list_lock); return tt_req_node; }
@@@ -1362,7 -1435,8 +1435,8 @@@ static int batadv_tt_global_valid(cons const struct batadv_tt_global_entry *tt_global_entry; const struct batadv_orig_node *orig_node = data_ptr;
- if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM) + if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM || + tt_common_entry->flags & BATADV_TT_CLIENT_TEMP) return 0;
tt_global_entry = container_of(tt_common_entry, @@@ -1506,9 -1580,9 +1580,9 @@@ out if (ret) kfree_skb(skb); if (ret && tt_req_node) { - spin_lock_bh(&bat_priv->tt_req_list_lock); + spin_lock_bh(&bat_priv->tt.req_list_lock); list_del(&tt_req_node->list); - spin_unlock_bh(&bat_priv->tt_req_list_lock); + spin_unlock_bh(&bat_priv->tt.req_list_lock); kfree(tt_req_node); } return ret; @@@ -1529,6 -1603,7 +1603,7 @@@ batadv_send_other_tt_response(struct ba uint16_t tt_len, tt_tot; struct sk_buff *skb = NULL; struct batadv_tt_query_packet *tt_response; + uint8_t *packet_pos; size_t len;
batadv_dbg(BATADV_DBG_TT, bat_priv, @@@ -1582,8 -1657,8 +1657,8 @@@ goto unlock;
skb_reserve(skb, ETH_HLEN); - tt_response = (struct batadv_tt_query_packet *)skb_put(skb, - len); + packet_pos = skb_put(skb, len); + tt_response = (struct batadv_tt_query_packet *)packet_pos; tt_response->ttvn = req_ttvn; tt_response->tt_data = htons(tt_tot);
@@@ -1599,7 -1674,7 +1674,7 @@@ ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
skb = batadv_tt_response_fill_table(tt_len, ttvn, - bat_priv->tt_global_hash, + bat_priv->tt.global_hash, primary_if, batadv_tt_global_valid, req_dst_orig_node); @@@ -1662,6 -1737,7 +1737,7 @@@ batadv_send_my_tt_response(struct batad uint16_t tt_len, tt_tot; struct sk_buff *skb = NULL; struct batadv_tt_query_packet *tt_response; + uint8_t *packet_pos; size_t len;
batadv_dbg(BATADV_DBG_TT, bat_priv, @@@ -1670,7 -1746,7 +1746,7 @@@ (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
- my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); + my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); req_ttvn = tt_request->ttvn;
orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); @@@ -1689,7 -1765,7 +1765,7 @@@ * is too big send the whole local translation table */ if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || - !bat_priv->tt_buff) + !bat_priv->tt.last_changeset) full_table = true; else full_table = false; @@@ -1698,8 -1774,8 +1774,8 @@@ * I'll send only one packet with as much TT entries as I can */ if (!full_table) { - spin_lock_bh(&bat_priv->tt_buff_lock); - tt_len = bat_priv->tt_buff_len; + spin_lock_bh(&bat_priv->tt.last_changeset_lock); + tt_len = bat_priv->tt.last_changeset_len; tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = sizeof(*tt_response) + tt_len; @@@ -1708,22 -1784,22 +1784,22 @@@ goto unlock;
skb_reserve(skb, ETH_HLEN); - tt_response = (struct batadv_tt_query_packet *)skb_put(skb, - len); + packet_pos = skb_put(skb, len); + tt_response = (struct batadv_tt_query_packet *)packet_pos; tt_response->ttvn = req_ttvn; tt_response->tt_data = htons(tt_tot);
tt_buff = skb->data + sizeof(*tt_response); - memcpy(tt_buff, bat_priv->tt_buff, - bat_priv->tt_buff_len); - spin_unlock_bh(&bat_priv->tt_buff_lock); + memcpy(tt_buff, bat_priv->tt.last_changeset, + bat_priv->tt.last_changeset_len); + spin_unlock_bh(&bat_priv->tt.last_changeset_lock); } else { - tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt); + tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num); tt_len *= sizeof(struct batadv_tt_change); - ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); + ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
skb = batadv_tt_response_fill_table(tt_len, ttvn, - bat_priv->tt_local_hash, + bat_priv->tt.local_hash, primary_if, batadv_tt_local_valid_entry, NULL); @@@ -1755,7 -1831,7 +1831,7 @@@ goto out;
unlock: - spin_unlock_bh(&bat_priv->tt_buff_lock); + spin_unlock_bh(&bat_priv->tt.last_changeset_lock); out: if (orig_node) batadv_orig_node_free_ref(orig_node); @@@ -1908,14 -1984,14 +1984,14 @@@ void batadv_handle_tt_response(struct b }
/* Delete the tt_req_node from pending tt_requests list */ - spin_lock_bh(&bat_priv->tt_req_list_lock); - list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { + spin_lock_bh(&bat_priv->tt.req_list_lock); + list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { if (!batadv_compare_eth(node->addr, tt_response->src)) continue; list_del(&node->list); kfree(node); } - spin_unlock_bh(&bat_priv->tt_req_list_lock); + spin_unlock_bh(&bat_priv->tt.req_list_lock);
/* Recalculate the CRC for this orig_node and store it */ orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); @@@ -1949,22 -2025,22 +2025,22 @@@ static void batadv_tt_roam_list_free(st { struct batadv_tt_roam_node *node, *safe;
- spin_lock_bh(&bat_priv->tt_roam_list_lock); + spin_lock_bh(&bat_priv->tt.roam_list_lock);
- list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { + list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { list_del(&node->list); kfree(node); }
- spin_unlock_bh(&bat_priv->tt_roam_list_lock); + spin_unlock_bh(&bat_priv->tt.roam_list_lock); }
static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) { struct batadv_tt_roam_node *node, *safe;
- spin_lock_bh(&bat_priv->tt_roam_list_lock); - list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { + spin_lock_bh(&bat_priv->tt.roam_list_lock); + list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { if (!batadv_has_timed_out(node->first_time, BATADV_ROAMING_MAX_TIME)) continue; @@@ -1972,7 -2048,7 +2048,7 @@@ list_del(&node->list); kfree(node); } - spin_unlock_bh(&bat_priv->tt_roam_list_lock); + spin_unlock_bh(&bat_priv->tt.roam_list_lock); }
/* This function checks whether the client already reached the @@@ -1987,11 -2063,11 +2063,11 @@@ static bool batadv_tt_check_roam_count( struct batadv_tt_roam_node *tt_roam_node; bool ret = false;
- spin_lock_bh(&bat_priv->tt_roam_list_lock); + spin_lock_bh(&bat_priv->tt.roam_list_lock); /* The new tt_req will be issued only if I'm not waiting for a * reply from the same orig_node yet */ - list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) { + list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) { if (!batadv_compare_eth(tt_roam_node->addr, client)) continue;
@@@ -2016,12 -2092,12 +2092,12 @@@ BATADV_ROAMING_MAX_COUNT - 1); memcpy(tt_roam_node->addr, client, ETH_ALEN);
- list_add(&tt_roam_node->list, &bat_priv->tt_roam_list); + list_add(&tt_roam_node->list, &bat_priv->tt.roam_list); ret = true; }
unlock: - spin_unlock_bh(&bat_priv->tt_roam_list_lock); + spin_unlock_bh(&bat_priv->tt.roam_list_lock); return ret; }
@@@ -2085,13 -2161,15 +2161,15 @@@ out static void batadv_tt_purge(struct work_struct *work) { struct delayed_work *delayed_work; + struct batadv_priv_tt *priv_tt; struct batadv_priv *bat_priv;
delayed_work = container_of(work, struct delayed_work, work); - bat_priv = container_of(delayed_work, struct batadv_priv, tt_work); + priv_tt = container_of(delayed_work, struct batadv_priv_tt, work); + bat_priv = container_of(priv_tt, struct batadv_priv, tt);
batadv_tt_local_purge(bat_priv); - batadv_tt_global_roam_purge(bat_priv); + batadv_tt_global_purge(bat_priv); batadv_tt_req_purge(bat_priv); batadv_tt_roam_purge(bat_priv);
@@@ -2100,7 -2178,7 +2178,7 @@@
void batadv_tt_free(struct batadv_priv *bat_priv) { - cancel_delayed_work_sync(&bat_priv->tt_work); + cancel_delayed_work_sync(&bat_priv->tt.work);
batadv_tt_local_table_free(bat_priv); batadv_tt_global_table_free(bat_priv); @@@ -2108,7 -2186,7 +2186,7 @@@ batadv_tt_changes_list_free(bat_priv); batadv_tt_roam_list_free(bat_priv);
- kfree(bat_priv->tt_buff); + kfree(bat_priv->tt.last_changeset); }
/* This function will enable or disable the specified flags for all the entries @@@ -2152,7 -2230,7 +2230,7 @@@ out /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) { - struct batadv_hashtable *hash = bat_priv->tt_local_hash; + struct batadv_hashtable *hash = bat_priv->tt.local_hash; struct batadv_tt_common_entry *tt_common; struct batadv_tt_local_entry *tt_local; struct hlist_node *node, *node_tmp; @@@ -2177,7 -2255,7 +2255,7 @@@ "Deleting local tt entry (%pM): pending\n", tt_common->addr);
- atomic_dec(&bat_priv->num_local_tt); + atomic_dec(&bat_priv->tt.local_entry_num); hlist_del_rcu(node); tt_local = container_of(tt_common, struct batadv_tt_local_entry, @@@ -2195,26 -2273,26 +2273,26 @@@ static int batadv_tt_commit_changes(str { uint16_t changed_num = 0;
- if (atomic_read(&bat_priv->tt_local_changes) < 1) + if (atomic_read(&bat_priv->tt.local_changes) < 1) return -ENOENT;
- changed_num = batadv_tt_set_flags(bat_priv->tt_local_hash, + changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, BATADV_TT_CLIENT_NEW, false);
/* all reset entries have to be counted as local entries */ - atomic_add(changed_num, &bat_priv->num_local_tt); + atomic_add(changed_num, &bat_priv->tt.local_entry_num); batadv_tt_local_purge_pending_clients(bat_priv); - bat_priv->tt_crc = batadv_tt_local_crc(bat_priv); + bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv);
/* Increment the TTVN only once per OGM interval */ - atomic_inc(&bat_priv->ttvn); + atomic_inc(&bat_priv->tt.vn); batadv_dbg(BATADV_DBG_TT, bat_priv, "Local changes committed, updating to ttvn %u\n", - (uint8_t)atomic_read(&bat_priv->ttvn)); - bat_priv->tt_poss_change = false; + (uint8_t)atomic_read(&bat_priv->tt.vn)); + bat_priv->tt.poss_change = false;
/* reset the sending counter */ - atomic_set(&bat_priv->tt_ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); + atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
return batadv_tt_changes_fill_buff(bat_priv, packet_buff, packet_buff_len, packet_min_len); @@@ -2234,7 -2312,7 +2312,7 @@@ int batadv_tt_append_diff(struct batadv
/* if the changes have been sent often enough */ if ((tt_num_changes < 0) && - (!batadv_atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) { + (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) { batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, packet_min_len, packet_min_len); tt_num_changes = 0; @@@ -2365,3 -2443,22 +2443,22 @@@ bool batadv_tt_global_client_is_roaming out: return ret; } + + bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig_node, + const unsigned char *addr) + { + bool ret = false; + + if (!batadv_tt_global_add(bat_priv, orig_node, addr, + BATADV_TT_CLIENT_TEMP, + atomic_read(&orig_node->last_ttvn))) + goto out; + + batadv_dbg(BATADV_DBG_TT, bat_priv, + "Added temporary global client (addr: %pM orig: %pM)\n", + addr, orig_node->orig); + ret = true; + out: + return ret; + } diff --combined net/batman-adv/translation-table.h index ffa8735,811fffd..811fffd --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@@ -59,6 -59,8 +59,8 @@@ int batadv_tt_append_diff(struct batadv int packet_min_len); bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, uint8_t *addr); - + bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig_node, + const unsigned char *addr);
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ diff --combined net/batman-adv/types.h index 12635fd,2ed82ca..2ed82ca --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@@ -145,6 -145,11 +145,11 @@@ struct batadv_bcast_duplist_entry #endif
enum batadv_counters { + BATADV_CNT_TX, + BATADV_CNT_TX_BYTES, + BATADV_CNT_TX_DROPPED, + BATADV_CNT_RX, + BATADV_CNT_RX_BYTES, BATADV_CNT_FORWARD, BATADV_CNT_FORWARD_BYTES, BATADV_CNT_MGMT_TX, @@@ -160,6 -165,67 +165,67 @@@ BATADV_CNT_NUM, };
+ /** + * struct batadv_priv_tt - per mesh interface translation table data + * @vn: translation table version number + * @local_changes: changes registered in an originator interval + * @poss_change: Detect an ongoing roaming phase. If true, then this node + * received a roaming_adv and has to inspect every packet directed to it to + * check whether it still is the true destination or not. This flag will be + * reset to false as soon as the this node's ttvn is increased + * @changes_list: tracks tt local changes within an originator interval + * @req_list: list of pending tt_requests + * @local_crc: Checksum of the local table, recomputed before sending a new OGM + */ + struct batadv_priv_tt { + atomic_t vn; + atomic_t ogm_append_cnt; + atomic_t local_changes; + bool poss_change; + struct list_head changes_list; + struct batadv_hashtable *local_hash; + struct batadv_hashtable *global_hash; + struct list_head req_list; + struct list_head roam_list; + spinlock_t changes_list_lock; /* protects changes */ + spinlock_t req_list_lock; /* protects req_list */ + spinlock_t roam_list_lock; /* protects roam_list */ + atomic_t local_entry_num; + uint16_t local_crc; + unsigned char *last_changeset; + int16_t last_changeset_len; + spinlock_t last_changeset_lock; /* protects last_changeset */ + struct delayed_work work; + }; + + #ifdef CONFIG_BATMAN_ADV_BLA + struct batadv_priv_bla { + atomic_t num_requests; /* number of bla requests in flight */ + struct batadv_hashtable *claim_hash; + struct batadv_hashtable *backbone_hash; + struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; + int bcast_duplist_curr; + struct batadv_bla_claim_dst claim_dest; + struct delayed_work work; + }; + #endif + + struct batadv_priv_gw { + struct hlist_head list; + spinlock_t list_lock; /* protects gw_list and curr_gw */ + struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ + atomic_t reselect; + }; + + struct batadv_priv_vis { + struct list_head send_list; + struct batadv_hashtable *hash; + spinlock_t hash_lock; /* protects hash */ + spinlock_t list_lock; /* protects info::recv_list */ + struct delayed_work work; + struct batadv_vis_info *my_info; + }; + struct batadv_priv { atomic_t mesh_state; struct net_device_stats stats; @@@ -179,64 -245,24 +245,24 @@@ atomic_t bcast_seqno; atomic_t bcast_queue_left; atomic_t batman_queue_left; - atomic_t ttvn; /* translation table version number */ - atomic_t tt_ogm_append_cnt; - atomic_t tt_local_changes; /* changes registered in a OGM interval */ - atomic_t bla_num_requests; /* number of bla requests in flight */ - /* The tt_poss_change flag is used to detect an ongoing roaming phase. - * If true, then I received a Roaming_adv and I have to inspect every - * packet directed to me to check whether I am still the true - * destination or not. This flag will be reset to false as soon as I - * increase my TTVN - */ - bool tt_poss_change; char num_ifaces; struct batadv_debug_log *debug_log; struct kobject *mesh_obj; struct dentry *debug_dir; struct hlist_head forw_bat_list; struct hlist_head forw_bcast_list; - struct hlist_head gw_list; - struct list_head tt_changes_list; /* tracks changes in a OGM int */ - struct list_head vis_send_list; struct batadv_hashtable *orig_hash; - struct batadv_hashtable *tt_local_hash; - struct batadv_hashtable *tt_global_hash; - #ifdef CONFIG_BATMAN_ADV_BLA - struct batadv_hashtable *claim_hash; - struct batadv_hashtable *backbone_hash; - #endif - struct list_head tt_req_list; /* list of pending tt_requests */ - struct list_head tt_roam_list; - struct batadv_hashtable *vis_hash; - #ifdef CONFIG_BATMAN_ADV_BLA - struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; - int bcast_duplist_curr; - struct batadv_bla_claim_dst claim_dest; - #endif spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ spinlock_t forw_bcast_list_lock; /* protects */ - spinlock_t tt_changes_list_lock; /* protects tt_changes */ - spinlock_t tt_req_list_lock; /* protects tt_req_list */ - spinlock_t tt_roam_list_lock; /* protects tt_roam_list */ - spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ - spinlock_t vis_hash_lock; /* protects vis_hash */ - spinlock_t vis_list_lock; /* protects vis_info::recv_list */ - atomic_t num_local_tt; - /* Checksum of the local table, recomputed before sending a new OGM */ - uint16_t tt_crc; - unsigned char *tt_buff; - int16_t tt_buff_len; - spinlock_t tt_buff_lock; /* protects tt_buff */ - struct delayed_work tt_work; struct delayed_work orig_work; - struct delayed_work vis_work; - struct delayed_work bla_work; - struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ - atomic_t gw_reselect; struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ - struct batadv_vis_info *my_vis_info; struct batadv_algo_ops *bat_algo_ops; + #ifdef CONFIG_BATMAN_ADV_BLA + struct batadv_priv_bla bla; + #endif + struct batadv_priv_gw gw; + struct batadv_priv_tt tt; + struct batadv_priv_vis vis; };
struct batadv_socket_client { @@@ -258,6 -284,7 +284,7 @@@ struct batadv_tt_common_entry uint8_t addr[ETH_ALEN]; struct hlist_node hash_entry; uint16_t flags; + unsigned long added_at; atomic_t refcount; struct rcu_head rcu; }; @@@ -277,6 -304,7 +304,7 @@@ struct batadv_tt_global_entry struct batadv_tt_orig_list_entry { struct batadv_orig_node *orig_node; uint8_t ttvn; + atomic_t refcount; struct rcu_head rcu; struct hlist_node list; }; diff --combined net/batman-adv/unicast.c index 0016464,f397232..f397232 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@@ -39,6 -39,7 +39,7 @@@ batadv_frag_merge_packet(struct list_he struct batadv_unicast_packet *unicast_packet; int hdr_len = sizeof(*unicast_packet); int uni_diff = sizeof(*up) - hdr_len; + uint8_t *packet_pos;
up = (struct batadv_unicast_frag_packet *)skb->data; /* set skb to the first part and tmp_skb to the second part */ @@@ -65,8 -66,8 +66,8 @@@ kfree_skb(tmp_skb);
memmove(skb->data + uni_diff, skb->data, hdr_len); - unicast_packet = (struct batadv_unicast_packet *)skb_pull(skb, - uni_diff); + packet_pos = skb_pull(skb, uni_diff); + unicast_packet = (struct batadv_unicast_packet *)packet_pos; unicast_packet->header.packet_type = BATADV_UNICAST;
return skb; @@@ -121,6 -122,7 +122,7 @@@ batadv_frag_search_packet(struct list_h { struct batadv_frag_packet_list_entry *tfp; struct batadv_unicast_frag_packet *tmp_up = NULL; + int is_head_tmp, is_head; uint16_t search_seqno;
if (up->flags & BATADV_UNI_FRAG_HEAD) @@@ -128,6 -130,8 +130,8 @@@ else search_seqno = ntohs(up->seqno)-1;
+ is_head = !!(up->flags & BATADV_UNI_FRAG_HEAD); + list_for_each_entry(tfp, head, list) {
if (!tfp->skb) @@@ -139,9 -143,8 +143,8 @@@ tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data;
if (tfp->seqno == search_seqno) { - - if ((tmp_up->flags & BATADV_UNI_FRAG_HEAD) != - (up->flags & BATADV_UNI_FRAG_HEAD)) + is_head_tmp = !!(tmp_up->flags & BATADV_UNI_FRAG_HEAD); + if (is_head_tmp != is_head) return tfp; else goto mov_tail; @@@ -334,8 -337,7 +337,7 @@@ find_router /* copy the destination for faster routing */ memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); /* set the destination tt version number */ - unicast_packet->ttvn = - (uint8_t)atomic_read(&orig_node->last_ttvn); + unicast_packet->ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
/* inform the destination node that we are still missing a correct route * for this client. The destination will receive this packet and will diff --combined net/batman-adv/vis.c index 2a2ea06,5abd145..5abd145 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@@ -41,13 -41,13 +41,13 @@@ static void batadv_free_info(struct kre bat_priv = info->bat_priv;
list_del_init(&info->send_list); - spin_lock_bh(&bat_priv->vis_list_lock); + spin_lock_bh(&bat_priv->vis.list_lock); list_for_each_entry_safe(entry, tmp, &info->recv_list, list) { list_del(&entry->list); kfree(entry); }
- spin_unlock_bh(&bat_priv->vis_list_lock); + spin_unlock_bh(&bat_priv->vis.list_lock); kfree_skb(info->skb_packet); kfree(info); } @@@ -94,7 -94,7 +94,7 @@@ static uint32_t batadv_vis_info_choose( static struct batadv_vis_info * batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data) { - struct batadv_hashtable *hash = bat_priv->vis_hash; + struct batadv_hashtable *hash = bat_priv->vis.hash; struct hlist_head *head; struct hlist_node *node; struct batadv_vis_info *vis_info, *vis_info_tmp = NULL; @@@ -252,7 -252,7 +252,7 @@@ int batadv_vis_seq_print_text(struct se struct hlist_head *head; struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_priv *bat_priv = netdev_priv(net_dev); - struct batadv_hashtable *hash = bat_priv->vis_hash; + struct batadv_hashtable *hash = bat_priv->vis.hash; uint32_t i; int ret = 0; int vis_server = atomic_read(&bat_priv->vis_mode); @@@ -264,12 -264,12 +264,12 @@@ if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE) goto out;
- spin_lock_bh(&bat_priv->vis_hash_lock); + spin_lock_bh(&bat_priv->vis.hash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; batadv_vis_seq_print_text_bucket(seq, head); } - spin_unlock_bh(&bat_priv->vis_hash_lock); + spin_unlock_bh(&bat_priv->vis.hash_lock);
out: if (primary_if) @@@ -285,7 -285,7 +285,7 @@@ static void batadv_send_list_add(struc { if (list_empty(&info->send_list)) { kref_get(&info->refcount); - list_add_tail(&info->send_list, &bat_priv->vis_send_list); + list_add_tail(&info->send_list, &bat_priv->vis.send_list); } }
@@@ -311,9 -311,9 +311,9 @@@ static void batadv_recv_list_add(struc return;
memcpy(entry->mac, mac, ETH_ALEN); - spin_lock_bh(&bat_priv->vis_list_lock); + spin_lock_bh(&bat_priv->vis.list_lock); list_add_tail(&entry->list, recv_list); - spin_unlock_bh(&bat_priv->vis_list_lock); + spin_unlock_bh(&bat_priv->vis.list_lock); }
/* returns 1 if this mac is in the recv_list */ @@@ -323,14 -323,14 +323,14 @@@ static int batadv_recv_list_is_in(struc { const struct batadv_recvlist_node *entry;
- spin_lock_bh(&bat_priv->vis_list_lock); + spin_lock_bh(&bat_priv->vis.list_lock); list_for_each_entry(entry, recv_list, list) { if (batadv_compare_eth(entry->mac, mac)) { - spin_unlock_bh(&bat_priv->vis_list_lock); + spin_unlock_bh(&bat_priv->vis.list_lock); return 1; } } - spin_unlock_bh(&bat_priv->vis_list_lock); + spin_unlock_bh(&bat_priv->vis.list_lock); return 0; }
@@@ -354,7 -354,7 +354,7 @@@ batadv_add_packet(struct batadv_priv *b
*is_new = 0; /* sanity check */ - if (!bat_priv->vis_hash) + if (!bat_priv->vis.hash) return NULL;
/* see if the packet is already in vis_hash */ @@@ -385,7 -385,7 +385,7 @@@ } } /* remove old entry */ - batadv_hash_remove(bat_priv->vis_hash, batadv_vis_info_cmp, + batadv_hash_remove(bat_priv->vis.hash, batadv_vis_info_cmp, batadv_vis_info_choose, old_info); batadv_send_list_del(old_info); kref_put(&old_info->refcount, batadv_free_info); @@@ -426,7 -426,7 +426,7 @@@ batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
/* try to add it */ - hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp, + hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp, batadv_vis_info_choose, info, &info->hash_entry); if (hash_added != 0) { @@@ -449,7 -449,7 +449,7 @@@ void batadv_receive_server_sync_packet(
make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC);
- spin_lock_bh(&bat_priv->vis_hash_lock); + spin_lock_bh(&bat_priv->vis.hash_lock); info = batadv_add_packet(bat_priv, vis_packet, vis_info_len, &is_new, make_broadcast); if (!info) @@@ -461,7 -461,7 +461,7 @@@ if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new) batadv_send_list_add(bat_priv, info); end: - spin_unlock_bh(&bat_priv->vis_hash_lock); + spin_unlock_bh(&bat_priv->vis.hash_lock); }
/* handle an incoming client update packet and schedule forward if needed. */ @@@ -484,7 -484,7 +484,7 @@@ void batadv_receive_client_update_packe batadv_is_my_mac(vis_packet->target_orig)) are_target = 1;
- spin_lock_bh(&bat_priv->vis_hash_lock); + spin_lock_bh(&bat_priv->vis.hash_lock); info = batadv_add_packet(bat_priv, vis_packet, vis_info_len, &is_new, are_target);
@@@ -505,7 -505,7 +505,7 @@@ }
end: - spin_unlock_bh(&bat_priv->vis_hash_lock); + spin_unlock_bh(&bat_priv->vis.hash_lock); }
/* Walk the originators and find the VIS server with the best tq. Set the packet @@@ -574,10 -574,11 +574,11 @@@ static int batadv_generate_vis_packet(s struct hlist_head *head; struct batadv_orig_node *orig_node; struct batadv_neigh_node *router; - struct batadv_vis_info *info = bat_priv->my_vis_info; + struct batadv_vis_info *info = bat_priv->vis.my_info; struct batadv_vis_packet *packet; struct batadv_vis_info_entry *entry; struct batadv_tt_common_entry *tt_common_entry; + uint8_t *packet_pos; int best_tq = -1; uint32_t i;
@@@ -618,8 -619,8 +619,8 @@@ goto next;
/* fill one entry into buffer. */ - entry = (struct batadv_vis_info_entry *) - skb_put(info->skb_packet, sizeof(*entry)); + packet_pos = skb_put(info->skb_packet, sizeof(*entry)); + entry = (struct batadv_vis_info_entry *)packet_pos; memcpy(entry->src, router->if_incoming->net_dev->dev_addr, ETH_ALEN); @@@ -636,7 -637,7 +637,7 @@@ next rcu_read_unlock(); }
- hash = bat_priv->tt_local_hash; + hash = bat_priv->tt.local_hash;
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@@ -644,9 -645,8 +645,8 @@@ rcu_read_lock(); hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) { - entry = (struct batadv_vis_info_entry *) - skb_put(info->skb_packet, - sizeof(*entry)); + packet_pos = skb_put(info->skb_packet, sizeof(*entry)); + entry = (struct batadv_vis_info_entry *)packet_pos; memset(entry->src, 0, ETH_ALEN); memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN); entry->quality = 0; /* 0 means TT */ @@@ -671,7 -671,7 +671,7 @@@ unlock static void batadv_purge_vis_packets(struct batadv_priv *bat_priv) { uint32_t i; - struct batadv_hashtable *hash = bat_priv->vis_hash; + struct batadv_hashtable *hash = bat_priv->vis.hash; struct hlist_node *node, *node_tmp; struct hlist_head *head; struct batadv_vis_info *info; @@@ -682,7 -682,7 +682,7 @@@ hlist_for_each_entry_safe(info, node, node_tmp, head, hash_entry) { /* never purge own data. */ - if (info == bat_priv->my_vis_info) + if (info == bat_priv->vis.my_info) continue;
if (batadv_has_timed_out(info->first_seen, @@@ -814,34 -814,36 +814,36 @@@ out /* called from timer; send (and maybe generate) vis packet. */ static void batadv_send_vis_packets(struct work_struct *work) { - struct delayed_work *delayed_work = - container_of(work, struct delayed_work, work); + struct delayed_work *delayed_work; struct batadv_priv *bat_priv; + struct batadv_priv_vis *priv_vis; struct batadv_vis_info *info;
- bat_priv = container_of(delayed_work, struct batadv_priv, vis_work); - spin_lock_bh(&bat_priv->vis_hash_lock); + delayed_work = container_of(work, struct delayed_work, work); + priv_vis = container_of(delayed_work, struct batadv_priv_vis, work); + bat_priv = container_of(priv_vis, struct batadv_priv, vis); + spin_lock_bh(&bat_priv->vis.hash_lock); batadv_purge_vis_packets(bat_priv);
if (batadv_generate_vis_packet(bat_priv) == 0) { /* schedule if generation was successful */ - batadv_send_list_add(bat_priv, bat_priv->my_vis_info); + batadv_send_list_add(bat_priv, bat_priv->vis.my_info); }
- while (!list_empty(&bat_priv->vis_send_list)) { - info = list_first_entry(&bat_priv->vis_send_list, + while (!list_empty(&bat_priv->vis.send_list)) { + info = list_first_entry(&bat_priv->vis.send_list, typeof(*info), send_list);
kref_get(&info->refcount); - spin_unlock_bh(&bat_priv->vis_hash_lock); + spin_unlock_bh(&bat_priv->vis.hash_lock);
batadv_send_vis_packet(bat_priv, info);
- spin_lock_bh(&bat_priv->vis_hash_lock); + spin_lock_bh(&bat_priv->vis.hash_lock); batadv_send_list_del(info); kref_put(&info->refcount, batadv_free_info); } - spin_unlock_bh(&bat_priv->vis_hash_lock); + spin_unlock_bh(&bat_priv->vis.hash_lock); batadv_start_vis_timer(bat_priv); }
@@@ -856,37 -858,37 +858,37 @@@ int batadv_vis_init(struct batadv_priv unsigned long first_seen; struct sk_buff *tmp_skb;
- if (bat_priv->vis_hash) + if (bat_priv->vis.hash) return 0;
- spin_lock_bh(&bat_priv->vis_hash_lock); + spin_lock_bh(&bat_priv->vis.hash_lock);
- bat_priv->vis_hash = batadv_hash_new(256); - if (!bat_priv->vis_hash) { + bat_priv->vis.hash = batadv_hash_new(256); + if (!bat_priv->vis.hash) { pr_err("Can't initialize vis_hash\n"); goto err; }
- bat_priv->my_vis_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC); - if (!bat_priv->my_vis_info) + bat_priv->vis.my_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC); + if (!bat_priv->vis.my_info) goto err;
len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN; - bat_priv->my_vis_info->skb_packet = dev_alloc_skb(len); - if (!bat_priv->my_vis_info->skb_packet) + bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len); + if (!bat_priv->vis.my_info->skb_packet) goto free_info;
- skb_reserve(bat_priv->my_vis_info->skb_packet, ETH_HLEN); - tmp_skb = bat_priv->my_vis_info->skb_packet; + skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN); + tmp_skb = bat_priv->vis.my_info->skb_packet; packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
/* prefill the vis info */ first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL); - bat_priv->my_vis_info->first_seen = first_seen; - INIT_LIST_HEAD(&bat_priv->my_vis_info->recv_list); - INIT_LIST_HEAD(&bat_priv->my_vis_info->send_list); - kref_init(&bat_priv->my_vis_info->refcount); - bat_priv->my_vis_info->bat_priv = bat_priv; + bat_priv->vis.my_info->first_seen = first_seen; + INIT_LIST_HEAD(&bat_priv->vis.my_info->recv_list); + INIT_LIST_HEAD(&bat_priv->vis.my_info->send_list); + kref_init(&bat_priv->vis.my_info->refcount); + bat_priv->vis.my_info->bat_priv = bat_priv; packet->header.version = BATADV_COMPAT_VERSION; packet->header.packet_type = BATADV_VIS; packet->header.ttl = BATADV_TTL; @@@ -894,28 -896,28 +896,28 @@@ packet->reserved = 0; packet->entries = 0;
- INIT_LIST_HEAD(&bat_priv->vis_send_list); + INIT_LIST_HEAD(&bat_priv->vis.send_list);
- hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp, + hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp, batadv_vis_info_choose, - bat_priv->my_vis_info, - &bat_priv->my_vis_info->hash_entry); + bat_priv->vis.my_info, + &bat_priv->vis.my_info->hash_entry); if (hash_added != 0) { pr_err("Can't add own vis packet into hash\n"); /* not in hash, need to remove it manually. */ - kref_put(&bat_priv->my_vis_info->refcount, batadv_free_info); + kref_put(&bat_priv->vis.my_info->refcount, batadv_free_info); goto err; }
- spin_unlock_bh(&bat_priv->vis_hash_lock); + spin_unlock_bh(&bat_priv->vis.hash_lock); batadv_start_vis_timer(bat_priv); return 0;
free_info: - kfree(bat_priv->my_vis_info); - bat_priv->my_vis_info = NULL; + kfree(bat_priv->vis.my_info); + bat_priv->vis.my_info = NULL; err: - spin_unlock_bh(&bat_priv->vis_hash_lock); + spin_unlock_bh(&bat_priv->vis.hash_lock); batadv_vis_quit(bat_priv); return -ENOMEM; } @@@ -933,23 -935,23 +935,23 @@@ static void batadv_free_info_ref(struc /* shutdown vis-server */ void batadv_vis_quit(struct batadv_priv *bat_priv) { - if (!bat_priv->vis_hash) + if (!bat_priv->vis.hash) return;
- cancel_delayed_work_sync(&bat_priv->vis_work); + cancel_delayed_work_sync(&bat_priv->vis.work);
- spin_lock_bh(&bat_priv->vis_hash_lock); + spin_lock_bh(&bat_priv->vis.hash_lock); /* properly remove, kill timers ... */ - batadv_hash_delete(bat_priv->vis_hash, batadv_free_info_ref, NULL); - bat_priv->vis_hash = NULL; - bat_priv->my_vis_info = NULL; - spin_unlock_bh(&bat_priv->vis_hash_lock); + batadv_hash_delete(bat_priv->vis.hash, batadv_free_info_ref, NULL); + bat_priv->vis.hash = NULL; + bat_priv->vis.my_info = NULL; + spin_unlock_bh(&bat_priv->vis.hash_lock); }
/* schedule packets for (re)transmission */ static void batadv_start_vis_timer(struct batadv_priv *bat_priv) { - INIT_DELAYED_WORK(&bat_priv->vis_work, batadv_send_vis_packets); - queue_delayed_work(batadv_event_workqueue, &bat_priv->vis_work, + INIT_DELAYED_WORK(&bat_priv->vis.work, batadv_send_vis_packets); + queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work, msecs_to_jiffies(BATADV_VIS_INTERVAL)); } diff --combined net/batman-adv/vis.h index 84e716e,873282f..873282f --- a/net/batman-adv/vis.h +++ b/net/batman-adv/vis.h @@@ -20,7 -20,7 +20,7 @@@ #ifndef _NET_BATMAN_ADV_VIS_H_ #define _NET_BATMAN_ADV_VIS_H_
- /* timeout of vis packets in miliseconds */ + /* timeout of vis packets in milliseconds */ #define BATADV_VIS_TIMEOUT 200000
int batadv_vis_seq_print_text(struct seq_file *seq, void *offset);