+static void batadv_v_ogm_send(struct work_struct *work) +{
- struct batadv_hard_iface *hard_iface;
- struct batadv_priv_bat_v *bat_v;
- struct batadv_priv *bat_priv;
- struct batadv_ogm2_packet *ogm2;
- struct sk_buff *skb;
- unsigned char *ogm_buff, *pkt_buff;
- int ogm_buff_len;
- uint16_t tvlv_len = 0;
- bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
- bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
- if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
goto out;
- ogm_buff = bat_priv->bat_v.ogm_buff;
- ogm_buff_len = bat_priv->bat_v.ogm_buff_len;
- /* tt changes have to be committed before the tvlv data is
* appended as it may alter the tt tvlv container
*/
- batadv_tt_local_commit_changes(bat_priv);
- tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, &ogm_buff,
&ogm_buff_len,
BATADV_OGM2_HLEN);
- bat_priv->bat_v.ogm_buff = ogm_buff;
- bat_priv->bat_v.ogm_buff_len = ogm_buff_len;
- skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + ogm_buff_len);
- if (!skb)
goto out;
- skb_reserve(skb, ETH_HLEN);
- pkt_buff = skb_put(skb, ogm_buff_len);
- memcpy(pkt_buff, ogm_buff, ogm_buff_len);
- ogm2 = (struct batadv_ogm2_packet *)skb->data;
- ogm2->seqno = htonl(atomic_read(&bat_priv->bat_v.ogm_seqno));
- atomic_inc(&bat_priv->bat_v.ogm_seqno);
- ogm2->tvlv_len = htons(tvlv_len);
- /* broadcast on every interface */
- rcu_read_lock();
- list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
if (hard_iface->soft_iface != bat_priv->soft_iface)
continue;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Sending own OGM2 packet (originator %pM, seqno %u, metric %u, TTL %d) on interface %s [%pM]\n",
ogm2->orig, ntohl(ogm2->seqno), ntohl(ogm2->metric),
ogm2->ttl, hard_iface->net_dev->name,
hard_iface->net_dev->dev_addr);
batadv_v_ogm_send_to_if(skb, hard_iface);
- }
- rcu_read_unlock();
- consume_skb(skb);
- batadv_v_ogm_start_timer(bat_priv);
+out:
- return;
If you jump to out because netdev_alloc_skb_ip_align() failed, don't you want to start the timer again? I would assume it is a transient problem not being able to get memory for the skb, and the next time the timer goes off it might work?
- bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN;
- ogm_buff = kmalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC);
Maybe use kzalloc to ensure it is zero?
Andrew