[04/10] batman-adv: Send neighbor discovery packets
Commit Message
This patch makes use of the previously introduced periodic tasks per
interface and actually sends neighbor discovery packets on these now.
Note: The TQ values of each neighbor are not being added yet to these NDPs
and also no evaluation of these packets is being done.
Signed-off-by: Linus Lüssing <linus.luessing@ascom.ch>
---
hard-interface.c | 5 ++++-
ndp.c | 36 +++++++++++++++++++++++++++++++++++-
types.h | 5 +++++
3 files changed, 44 insertions(+), 2 deletions(-)
Comments
On Tuesday 14 December 2010 10:58:10 Linus Lüssing wrote:
> @@ -331,7 +332,9 @@ int hardif_enable_interface(struct batman_if
> *batman_if, char *iface_name)
>
> atomic_set(&batman_if->seqno, 1);
> atomic_set(&batman_if->frag_seqno, 1);
> - ndp_init(batman_if);
> + ret = ndp_init(batman_if);
> + if (ret)
> + goto err;
This introduces a potential memory leak, next to other problems. If the code
jumps to "err" batman_if->packet_buff is not free()'d, bat_priv->num_ifaces is
wrong, the orig_hash has one interface too much, etc. Please check the error
handling here and make sure that there is a clean rollback.
> + skb = skb_clone(batman_if->ndp_skb, GFP_ATOMIC);
> + ndp_packet = (struct batman_packet_ndp*)skb->data;
> + ndp_packet->seqno = htonl(atomic_read(&batman_if->ndp_seqno));
> + ndp_packet->num_neighbors = 0;
> + memcpy(ndp_packet->orig, bat_priv->primary_if->net_dev->dev_addr,
> + ETH_ALEN);
I don't think you want to use skb_clone() here as it "only" copies the sk_buff
and not skb->data. That means all threads write on the same skb->data ...
> +struct neigh_entry {
> + uint8_t addr[ETH_ALEN];
> + uint8_t rq;
> +};
Again, this struct is not used and can be added later.
Checkpatch gives 2 errors ..
Cheers,
Marek
@@ -284,6 +284,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
{
struct bat_priv *bat_priv;
struct batman_packet_ogm *batman_packet_ogm;
+ int ret;
if (batman_if->if_status != IF_NOT_IN_USE)
goto out;
@@ -331,7 +332,9 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
atomic_set(&batman_if->seqno, 1);
atomic_set(&batman_if->frag_seqno, 1);
- ndp_init(batman_if);
+ ret = ndp_init(batman_if);
+ if (ret)
+ goto err;
bat_info(batman_if->soft_iface, "Adding interface: %s\n",
batman_if->net_dev->name);
@@ -20,10 +20,21 @@ static void ndp_send(struct work_struct *work)
struct batman_if *batman_if = container_of(work, struct batman_if,
ndp_wq.work);
struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
+ struct batman_packet_ndp *ndp_packet;
+ struct sk_buff *skb;
+
+ skb = skb_clone(batman_if->ndp_skb, GFP_ATOMIC);
+ ndp_packet = (struct batman_packet_ndp*)skb->data;
+ ndp_packet->seqno = htonl(atomic_read(&batman_if->ndp_seqno));
+ ndp_packet->num_neighbors = 0;
+ memcpy(ndp_packet->orig, bat_priv->primary_if->net_dev->dev_addr,
+ ETH_ALEN);
bat_dbg(DBG_BATMAN, bat_priv,
"batman-adv:Sending ndp packet on interface %s, seqno %d\n",
- batman_if->net_dev, atomic_read(&batman_if->ndp_seqno));
+ batman_if->net_dev, ntohl(ndp_packet->seqno));
+
+ send_skb_packet(skb, batman_if, broadcast_addr);
atomic_inc(&batman_if->ndp_seqno);
start_ndp_timer(batman_if);
@@ -31,14 +42,37 @@ static void ndp_send(struct work_struct *work)
int ndp_init(struct batman_if *batman_if)
{
+ struct batman_packet_ndp *ndp_packet;
+
atomic_set(&batman_if->ndp_interval, 500);
atomic_set(&batman_if->ndp_seqno, 0);
+
+ batman_if->ndp_skb =
+ dev_alloc_skb(ETH_DATA_LEN + sizeof(struct ethhdr));
+ if (!batman_if->ndp_skb) {
+ printk(KERN_ERR "batman-adv: Can't add "
+ "local interface packet (%s): out of memory\n",
+ batman_if->net_dev->name);
+ goto err;
+ }
+ skb_reserve(batman_if->ndp_skb, sizeof(struct ethhdr) +
+ sizeof(struct batman_packet_ndp));
+ ndp_packet = (struct batman_packet_ndp*)
+ skb_push(batman_if->ndp_skb, sizeof(struct batman_packet_ndp));
+ memset(ndp_packet, 0, sizeof(struct batman_packet_ndp));
+
+ ndp_packet->packet_type = BAT_PACKET_NDP;
+ ndp_packet->version = COMPAT_VERSION;
+
INIT_DELAYED_WORK(&batman_if->ndp_wq, ndp_send);
return 0;
+err:
+ return 1;
}
void ndp_free(struct batman_if *batman_if)
{
stop_ndp_timer(batman_if);
+ dev_kfree_skb(batman_if->ndp_skb);
}
@@ -49,6 +49,7 @@ struct batman_if {
struct rcu_head rcu;
atomic_t ndp_interval;
atomic_t ndp_seqno;
+ struct sk_buff *ndp_skb;
struct delayed_work ndp_wq;
};
@@ -122,6 +123,10 @@ struct neigh_node {
struct batman_if *if_incoming;
};
+struct neigh_entry {
+ uint8_t addr[ETH_ALEN];
+ uint8_t rq;
+};
struct bat_priv {
atomic_t mesh_state;