From patchwork Sat Jun 11 10:25:58 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Lindner X-Patchwork-Id: 1145 Return-Path: Received: from nm10.bullet.mail.ukl.yahoo.com (nm10.bullet.mail.ukl.yahoo.com [217.146.182.251]) by open-mesh.org (Postfix) with SMTP id 0738D1543D5 for ; Sat, 11 Jun 2011 12:26:04 +0200 (CEST) Authentication-Results: open-mesh.org; dkim=pass (1024-bit key) header.i=@yahoo.de; dkim-adsp=none Received: from [217.146.183.209] by nm10.bullet.mail.ukl.yahoo.com with NNFMP; 11 Jun 2011 10:26:04 -0000 Received: from [77.238.184.62] by tm2.bullet.mail.ukl.yahoo.com with NNFMP; 11 Jun 2011 10:26:04 -0000 Received: from [127.0.0.1] by smtp131.mail.ukl.yahoo.com with NNFMP; 11 Jun 2011 10:26:04 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.de; s=s1024; t=1307787964; bh=ZElTbfrSMR6H0tP8lw/ylRarhK0efTPOkkvxMBbIFY0=; h=X-Yahoo-Newman-Id:X-Yahoo-Newman-Property:X-YMail-OSG:X-Yahoo-SMTP:Received:From:To:Cc:Subject:Date:Message-Id:X-Mailer:In-Reply-To:References; b=wRQpD8HtAN0EXsNwDi1jWc54kn3IPg36+qY3Xs7pbyGUcZP1oyAvW9EYkOv4po0IuANWxeNCGoWWhryAgWX6x9P3oAfgsCgGa9kBWzZXZjFkILr3gl2x0Sg6wITnwUsbAJm6O6Gk0E3zs8ollaGRPgZWIYgreFQjvJD82f6CYTc= X-Yahoo-Newman-Id: 14823.43660.bm@smtp131.mail.ukl.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: aK15xcwVM1k_LYTzXQA4Q8Qsox5X.Ra3Ab5UEI3Cgoux4pp p5LmupkMles0Xk5JdFNYM4gyZiWtF14tmHrU.jl1p_Py2q51xKHn0ra8PUVY 9JJ11ZQ96Ngc6GPFlS5p3h4jWj2MX8loYS6jYR4kDpnJP2RbRKh6dHGHHtIG TRQvsdB1YwYn5LWq8foHBWev10gy2oTU1YKDB7Ae2c0XyoWWiXy38hSpN3up itPL7323dP386NEWBr1uSIV1.Z.N0hFvCyJcT1IB1F4qi3yKBzfZrkB63Hru 2j8JTla9K6GqAwmd4Eil4SIaU1lMFC8ar1OsxtYt.aSjmiUVoxAH_tfsCgCe G X-Yahoo-SMTP: tW.h3tiswBBMXO2coYcbPigGD5Lt6zY_.Zc- Received: from localhost (lindner_marek@90.35.102.28 with plain) by smtp131.mail.ukl.yahoo.com with SMTP; 11 Jun 2011 10:26:03 +0000 GMT From: Marek Lindner To: b.a.t.m.a.n@lists.open-mesh.org Date: Sat, 11 Jun 2011 12:25:58 +0200 Message-Id: <1307787958-25414-1-git-send-email-lindner_marek@yahoo.de> X-Mailer: git-send-email 1.7.5.3 In-Reply-To: <1304975758-9412-1-git-send-email-ordex@autistici.org> References: <1304975758-9412-1-git-send-email-ordex@autistici.org> Cc: Marek Lindner Subject: [B.A.T.M.A.N.] [PATCHv6 3/3] batman-adv: improved gateway tq-based selection X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.13 Precedence: list Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 11 Jun 2011 10:26:05 -0000 From: Antonio Quartulli If a client issues a DHCPREQUEST for renewal, the packet is dropped if the old destination (the old gateway for the client) TQ is smaller than the current best gateway TQ less GW_THRESHOLD Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- * if gw_is_target() returns a value smaller than zero in interface_tx() the code does not decrement orig_node's refcount gateway_client.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++- gateway_client.h | 3 +- main.h | 3 +- soft-interface.c | 10 ++++- 4 files changed, 104 insertions(+), 6 deletions(-) diff --git a/gateway_client.c b/gateway_client.c index 64505ee..d90463a 100644 --- a/gateway_client.c +++ b/gateway_client.c @@ -25,11 +25,17 @@ #include "gateway_common.h" #include "hard-interface.h" #include "originator.h" +#include "routing.h" #include #include #include #include +/* This is the offset of the options field in a dhcp packet starting at + * the beginning of the dhcp header */ +#define DHCP_OPTIONS_OFFSET 240 +#define DHCP_REQUEST 3 + static void gw_node_free_ref(struct gw_node *gw_node) { if (atomic_dec_and_test(&gw_node->refcount)) @@ -509,14 +515,75 @@ out: return ret; } -int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) +static bool is_type_dhcprequest(struct sk_buff *skb, int header_len) +{ + int ret = false; + unsigned char *p; + int pkt_len; + + if (skb_linearize(skb) < 0) + goto out; + + pkt_len = skb_headlen(skb); + + if (pkt_len < header_len + DHCP_OPTIONS_OFFSET + 1) + goto out; + + p = skb->data + header_len + DHCP_OPTIONS_OFFSET; + pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1; + + /* Access the dhcp option lists. Each entry is made up by: + * - octect 1: option type + * - octect 2: option data len (only if type != 255 and 0) + * - octect 3: option data */ + while (*p != 255 && !ret) { + /* p now points to the first octect: option type */ + if (*p == 53) { + /* type 53 is the message type option. + * Jump the len octect and go to the data octect */ + if (pkt_len < 2) + goto out; + p += 2; + + /* check if the message type is what we need */ + if (*p == DHCP_REQUEST) + ret = true; + break; + } else if (*p == 0) { + /* option type 0 (padding), just go forward */ + if (pkt_len < 1) + goto out; + pkt_len--; + p++; + } else { + /* This is any other option. So we get the length... */ + if (pkt_len < 1) + goto out; + pkt_len--; + p++; + + /* ...and then we jump over the data */ + if (pkt_len < *p) + goto out; + pkt_len -= *p; + p += (*p); + } + } +out: + return ret; +} + +int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, + struct orig_node *old_gw) { struct ethhdr *ethhdr; struct iphdr *iphdr; struct ipv6hdr *ipv6hdr; struct udphdr *udphdr; struct gw_node *curr_gw; + struct neigh_node *neigh_curr = NULL, *neigh_old = NULL; unsigned int header_len = 0; + int ret = 1; if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) return 0; @@ -584,7 +651,30 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) if (!curr_gw) return 0; + /* If old_gw != NULL then this packet is unicast. + * So, at this point we have to check the message type: if it is a + * DHCPREQUEST we have to decide whether to drop it or not */ + if (old_gw && curr_gw->orig_node != old_gw) { + if (is_type_dhcprequest(skb, header_len)) { + /* If the dhcp packet has been sent to a different gw, + * we have to evaluate whether the old gw is still + * reliable enough */ + neigh_curr = find_router(bat_priv, curr_gw->orig_node, + NULL); + neigh_old = find_router(bat_priv, old_gw, NULL); + if (!neigh_curr || !neigh_old) + goto free_neigh; + if (neigh_curr->tq_avg - neigh_old->tq_avg < + GW_THRESHOLD) + ret = -1; + } + } +free_neigh: + if (neigh_old) + neigh_node_free_ref(neigh_old); + if (neigh_curr) + neigh_node_free_ref(neigh_curr); if (curr_gw) gw_node_free_ref(curr_gw); - return 1; + return ret; } diff --git a/gateway_client.h b/gateway_client.h index 1ce8c60..b9b983c 100644 --- a/gateway_client.h +++ b/gateway_client.h @@ -31,6 +31,7 @@ void gw_node_update(struct bat_priv *bat_priv, void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_purge(struct bat_priv *bat_priv); int gw_client_seq_print_text(struct seq_file *seq, void *offset); -int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb); +int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, + struct orig_node *old_gw); #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ diff --git a/main.h b/main.h index 7f3768e..059866c 100644 --- a/main.h +++ b/main.h @@ -91,7 +91,6 @@ enum mesh_state { #define BCAST_QUEUE_LEN 256 #define BATMAN_QUEUE_LEN 256 - enum uev_action { UEV_ADD = 0, UEV_DEL, @@ -102,6 +101,8 @@ enum uev_type { UEV_GW = 0 }; +#define GW_THRESHOLD 50 + /* * Debug Messages */ diff --git a/soft-interface.c b/soft-interface.c index b268f85..7aeed0d 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -30,6 +30,7 @@ #include "gateway_common.h" #include "gateway_client.h" #include "bat_sysfs.h" +#include "originator.h" #include #include #include @@ -561,6 +562,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) struct bcast_packet *bcast_packet; struct vlan_ethhdr *vhdr; struct softif_neigh *curr_softif_neigh = NULL; + struct orig_node *orig_node = NULL; int data_len = skb->len, ret; short vid = -1; bool do_bcast = false; @@ -595,8 +597,10 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* Register the client MAC in the transtable */ tt_local_add(soft_iface, ethhdr->h_source); - if (is_multicast_ether_addr(ethhdr->h_dest)) { - ret = gw_is_target(bat_priv, skb); + orig_node = transtable_search(bat_priv, ethhdr->h_dest); + if (is_multicast_ether_addr(ethhdr->h_dest) || + (orig_node && orig_node->gw_flags)) { + ret = gw_is_target(bat_priv, skb, orig_node); if (ret < 0) goto dropped; @@ -656,6 +660,8 @@ end: softif_neigh_free_ref(curr_softif_neigh); if (primary_if) hardif_free_ref(primary_if); + if (orig_node) + orig_node_free_ref(orig_node); return NETDEV_TX_OK; }