Hi,
here comes the second revision of the gateway style patches. Only a few things changed: * rebased on top of current head * time_after / time_before bug was squashed * gw_sel_class & gw_bandwidth default values were moved into softif_create() * indentation was improved
Unless someone objects I'll merge the patches this weekend.
Regards, Marek
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- batman-adv/gateway_client.c | 30 +++++++++--------------------- batman-adv/gateway_client.h | 3 +-- batman-adv/main.c | 2 +- batman-adv/originator.c | 2 +- 4 files changed, 12 insertions(+), 25 deletions(-)
diff --git a/batman-adv/gateway_client.c b/batman-adv/gateway_client.c index 24c12b4..e10dc90 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -305,7 +305,7 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) return gw_node_update(bat_priv, orig_node, 0); }
-void gw_node_purge_deleted(struct bat_priv *bat_priv) +void gw_node_purge(struct bat_priv *bat_priv) { struct gw_node *gw_node; struct hlist_node *node, *node_tmp; @@ -314,32 +314,20 @@ void gw_node_purge_deleted(struct bat_priv *bat_priv) spin_lock_bh(&bat_priv->gw_list_lock);
hlist_for_each_entry_safe(gw_node, node, node_tmp, - &bat_priv->gw_list, list) { - if ((gw_node->deleted) && - (time_after(jiffies, gw_node->deleted + timeout))) { - - hlist_del_rcu(&gw_node->list); - call_rcu(&gw_node->rcu, gw_node_free_rcu); - } - } - - spin_unlock_bh(&bat_priv->gw_list_lock); -} - -void gw_node_list_free(struct bat_priv *bat_priv) -{ - struct gw_node *gw_node; - struct hlist_node *node, *node_tmp; + &bat_priv->gw_list, list) { + if (((!gw_node->deleted) || + (time_before(jiffies, gw_node->deleted + timeout))) && + atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) + continue;
- spin_lock_bh(&bat_priv->gw_list_lock); + if (bat_priv->curr_gw == gw_node) + gw_deselect(bat_priv);
- hlist_for_each_entry_safe(gw_node, node, node_tmp, - &bat_priv->gw_list, list) { hlist_del_rcu(&gw_node->list); call_rcu(&gw_node->rcu, gw_node_free_rcu); }
- gw_deselect(bat_priv); + spin_unlock_bh(&bat_priv->gw_list_lock); }
diff --git a/batman-adv/gateway_client.h b/batman-adv/gateway_client.h index ce0b4f0..38699ba 100644 --- a/batman-adv/gateway_client.h +++ b/batman-adv/gateway_client.h @@ -29,8 +29,7 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_update(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t new_gwflags); void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); -void gw_node_purge_deleted(struct bat_priv *bat_priv); -void gw_node_list_free(struct bat_priv *bat_priv); +void gw_node_purge(struct bat_priv *bat_priv); int gw_client_seq_print_text(struct seq_file *seq, void *offset); bool gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb);
diff --git a/batman-adv/main.c b/batman-adv/main.c index e4e4eca..c91e635 100644 --- a/batman-adv/main.c +++ b/batman-adv/main.c @@ -132,7 +132,7 @@ void mesh_free(struct net_device *soft_iface)
vis_quit(bat_priv);
- gw_node_list_free(bat_priv); + gw_node_purge(bat_priv); originator_free(bat_priv);
hna_local_free(bat_priv); diff --git a/batman-adv/originator.c b/batman-adv/originator.c index 8930446..89ec021 100644 --- a/batman-adv/originator.c +++ b/batman-adv/originator.c @@ -293,7 +293,7 @@ static void _purge_orig(struct bat_priv *bat_priv)
spin_unlock_bh(&bat_priv->orig_hash_lock);
- gw_node_purge_deleted(bat_priv); + gw_node_purge(bat_priv); gw_election(bat_priv);
softif_neigh_purge(bat_priv);
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- batman-adv/gateway_client.c | 31 +++++++++++++++++-------------- batman-adv/gateway_client.h | 2 +- batman-adv/soft-interface.c | 16 ++++++++++------ 3 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/batman-adv/gateway_client.c b/batman-adv/gateway_client.c index e10dc90..2e05dd4 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -399,54 +399,57 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) return 0; }
-bool 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 ethhdr *ethhdr; struct iphdr *iphdr; struct udphdr *udphdr; unsigned int header_len = 0;
- if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT) - return false; - - if (!bat_priv->curr_gw) - return false; + if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) + return 0;
/* check for ethernet header */ if (!pskb_may_pull(skb, header_len + ETH_HLEN)) - return false; + return 0; ethhdr = (struct ethhdr *)skb->data; header_len += ETH_HLEN;
/* check for initial vlan header */ if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { if (!pskb_may_pull(skb, header_len + VLAN_HLEN)) - return false; + return 0; ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); header_len += VLAN_HLEN; }
/* check for ip header */ if (ntohs(ethhdr->h_proto) != ETH_P_IP) - return false; + return 0;
if (!pskb_may_pull(skb, header_len + sizeof(struct iphdr))) - return false; + return 0; iphdr = (struct iphdr *)(skb->data + header_len); header_len += iphdr->ihl * 4;
/* check for udp header */ if (iphdr->protocol != IPPROTO_UDP) - return false; + return 0;
if (!pskb_may_pull(skb, header_len + sizeof(struct udphdr))) - return false; + return 0; udphdr = (struct udphdr *)(skb->data + header_len); header_len += sizeof(struct udphdr);
/* check for bootp port */ if (ntohs(udphdr->dest) != 67) - return false; + return 0; + + if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) + return -1; + + if (!bat_priv->curr_gw) + return 0;
- return true; + return 1; } diff --git a/batman-adv/gateway_client.h b/batman-adv/gateway_client.h index 38699ba..4585e65 100644 --- a/batman-adv/gateway_client.h +++ b/batman-adv/gateway_client.h @@ -31,6 +31,6 @@ 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); -bool 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);
#endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ diff --git a/batman-adv/soft-interface.c b/batman-adv/soft-interface.c index e16c61b..836c452 100644 --- a/batman-adv/soft-interface.c +++ b/batman-adv/soft-interface.c @@ -347,7 +347,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) struct vlan_ethhdr *vhdr; int data_len = skb->len, ret; short vid = -1; - bool bcast_dst = false, do_bcast = true; + bool do_bcast = false;
if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto dropped; @@ -378,14 +378,18 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* TODO: check this for locks */ hna_local_add(soft_iface, ethhdr->h_source);
- if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) - bcast_dst = true; + if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) { + ret = gw_is_target(bat_priv, skb);
- if ((bcast_dst) && gw_is_target(bat_priv, skb)) - do_bcast = false; + if (ret < 0) + goto dropped; + + if (ret == 0) + do_bcast = true; + }
/* ethernet packet should be broadcasted */ - if (bcast_dst && do_bcast) { + if (do_bcast) { if (!bat_priv->primary_if) goto dropped;
The Linux kernel guidelines require each sysfs file to have a single value / purpose, therefore it is necessary to split up the sysfs gateway files.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- batman-adv/bat_sysfs.c | 10 ++++++++++ batman-adv/gateway_client.c | 6 +++--- batman-adv/gateway_common.c | 5 ++++- batman-adv/routing.c | 5 ++++- batman-adv/soft-interface.c | 1 + batman-adv/types.h | 1 + 6 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/batman-adv/bat_sysfs.c b/batman-adv/bat_sysfs.c index 8e3dbef..0f39213 100644 --- a/batman-adv/bat_sysfs.c +++ b/batman-adv/bat_sysfs.c @@ -251,6 +251,12 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, return count; }
+static void post_gw_deselect(struct net_device *net_dev) +{ + struct bat_priv *bat_priv = netdev_priv(net_dev); + gw_deselect(bat_priv); +} + static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -261,6 +267,7 @@ static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr,
switch (gw_mode) { case GW_MODE_CLIENT: + gw_class = atomic_read(&bat_priv->gw_sel_class); bytes_written = sprintf(buff, "%s (gw_class: %i)\n", GW_MODE_CLIENT_NAME, gw_class); break; @@ -298,6 +305,8 @@ static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); BAT_ATTR_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL); +BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE, + post_gw_deselect); #ifdef CONFIG_BATMAN_ADV_DEBUG BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL); #endif @@ -310,6 +319,7 @@ static struct bat_attribute *mesh_attrs[] = { &bat_attr_gw_mode, &bat_attr_orig_interval, &bat_attr_hop_penalty, + &bat_attr_gw_sel_class, #ifdef CONFIG_BATMAN_ADV_DEBUG &bat_attr_log_level, #endif diff --git a/batman-adv/gateway_client.c b/batman-adv/gateway_client.c index 2e05dd4..56c52b0 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -116,7 +116,7 @@ void gw_election(struct bat_priv *bat_priv) if (gw_node->deleted) continue;
- switch (atomic_read(&bat_priv->gw_class)) { + switch (atomic_read(&bat_priv->gw_sel_class)) { case 1: /* fast connection */ gw_srv_class_to_kbit(gw_node->orig_node->gw_flags, &down, &up); @@ -215,8 +215,8 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) * if the routing class is greater than 3 the value tells us how much * greater the TQ value of the new gateway must be **/ - if ((atomic_read(&bat_priv->gw_class) > 3) && - (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_class))) + if ((atomic_read(&bat_priv->gw_sel_class) > 3) && + (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class))) return;
bat_dbg(DBG_BATMAN, bat_priv, diff --git a/batman-adv/gateway_common.c b/batman-adv/gateway_common.c index a88ce41..330167e 100644 --- a/batman-adv/gateway_common.c +++ b/batman-adv/gateway_common.c @@ -236,12 +236,15 @@ next:
switch (gw_mode_tmp) { case GW_MODE_CLIENT: + gw_class_tmp = atomic_read(&bat_priv->gw_sel_class); if ((gw_mode_tmp == GW_MODE_CLIENT) && (!gw_class_tmp)) gw_class_tmp = 20;
bat_info(net_dev, "Changing gateway mode from: '%s' to: '%s' " - "(gw_class: %ld)\n", + "(gw_sel_class: %ld)\n", gw_mode_curr_str, gw_mode_tmp_str, gw_class_tmp); + + atomic_set(&bat_priv->gw_sel_class, gw_class_tmp); break; case GW_MODE_SERVER: if (!down) diff --git a/batman-adv/routing.c b/batman-adv/routing.c index e75337d..9f31167 100644 --- a/batman-adv/routing.c +++ b/batman-adv/routing.c @@ -32,6 +32,7 @@ #include "ring_buffer.h" #include "vis.h" #include "aggregation.h" +#include "gateway_common.h" #include "gateway_client.h" #include "unicast.h"
@@ -330,7 +331,9 @@ update_gw: orig_node->gw_flags = batman_packet->gw_flags;
/* restart gateway selection if fast or late switching was enabled */ - if ((orig_node->gw_flags) && (atomic_read(&bat_priv->gw_class) > 2)) + if ((orig_node->gw_flags) && + (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) && + (atomic_read(&bat_priv->gw_sel_class) > 2)) gw_check_election(bat_priv, orig_node); }
diff --git a/batman-adv/soft-interface.c b/batman-adv/soft-interface.c index 836c452..7b2673c 100644 --- a/batman-adv/soft-interface.c +++ b/batman-adv/soft-interface.c @@ -591,6 +591,7 @@ struct net_device *softif_create(char *name) atomic_set(&bat_priv->bonding, 0); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); + atomic_set(&bat_priv->gw_sel_class, 0); atomic_set(&bat_priv->gw_class, 0); atomic_set(&bat_priv->orig_interval, 1000); atomic_set(&bat_priv->hop_penalty, 10); diff --git a/batman-adv/types.h b/batman-adv/types.h index 2678ce1..b68add4 100644 --- a/batman-adv/types.h +++ b/batman-adv/types.h @@ -128,6 +128,7 @@ struct bat_priv { atomic_t fragmentation; /* boolean */ atomic_t vis_mode; /* VIS_TYPE_* */ atomic_t gw_mode; /* GW_MODE_* */ + atomic_t gw_sel_class; /* uint */ atomic_t gw_class; /* uint */ atomic_t orig_interval; /* uint */ atomic_t hop_penalty; /* uint */
The Linux kernel guidelines require each sysfs file to have a single value / purpose, therefore it is necessary to split up the sysfs gateway files.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- batman-adv/bat_sysfs.c | 37 ++++++++++++-- batman-adv/gateway_client.c | 6 +- batman-adv/gateway_common.c | 115 ++++++++++++++++++++++++++++++++++++++++--- batman-adv/gateway_common.h | 3 +- batman-adv/send.c | 2 +- batman-adv/soft-interface.c | 2 +- batman-adv/types.h | 2 +- 7 files changed, 149 insertions(+), 18 deletions(-)
diff --git a/batman-adv/bat_sysfs.c b/batman-adv/bat_sysfs.c index 0f39213..f937f6f 100644 --- a/batman-adv/bat_sysfs.c +++ b/batman-adv/bat_sysfs.c @@ -262,8 +262,7 @@ static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr, { struct bat_priv *bat_priv = kobj_to_batpriv(kobj); int down, up, bytes_written; - int gw_mode = atomic_read(&bat_priv->gw_mode); - int gw_class = atomic_read(&bat_priv->gw_class); + int gw_class, gw_mode = atomic_read(&bat_priv->gw_mode);
switch (gw_mode) { case GW_MODE_CLIENT: @@ -272,7 +271,8 @@ static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr, GW_MODE_CLIENT_NAME, gw_class); break; case GW_MODE_SERVER: - gw_srv_class_to_kbit(gw_class, &down, &up); + gw_class = atomic_read(&bat_priv->gw_bandwidth); + gw_bandwidth_to_kbit(gw_class, &down, &up); bytes_written = sprintf(buff, "%s (gw_class: %i " "-> propagating: %i%s/%i%s)\n", @@ -292,12 +292,38 @@ static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr, }
static ssize_t store_gw_mode(struct kobject *kobj, struct attribute *attr, - char *buff, size_t count) + char *buff, size_t count) { struct net_device *net_dev = kobj_to_netdev(kobj); return gw_mode_set(net_dev, buff, count); }
+static ssize_t show_gw_bwidth(struct kobject *kobj, struct attribute *attr, + char *buff) +{ + struct bat_priv *bat_priv = kobj_to_batpriv(kobj); + int down, up; + int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth); + + gw_bandwidth_to_kbit(gw_bandwidth, &down, &up); + return sprintf(buff, "%i%s/%i%s\n", + (down > 2048 ? down / 1024 : down), + (down > 2048 ? "MBit" : "KBit"), + (up > 2048 ? up / 1024 : up), + (up > 2048 ? "MBit" : "KBit")); +} + +static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr, + char *buff, size_t count) +{ + struct net_device *net_dev = kobj_to_netdev(kobj); + + if (buff[count - 1] == '\n') + buff[count - 1] = '\0'; + + return gw_bandwidth_set(net_dev, buff, count); +} + BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); @@ -307,6 +333,8 @@ BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); BAT_ATTR_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL); BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE, post_gw_deselect); +static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth, + store_gw_bwidth); #ifdef CONFIG_BATMAN_ADV_DEBUG BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL); #endif @@ -320,6 +348,7 @@ static struct bat_attribute *mesh_attrs[] = { &bat_attr_orig_interval, &bat_attr_hop_penalty, &bat_attr_gw_sel_class, + &bat_attr_gw_bandwidth, #ifdef CONFIG_BATMAN_ADV_DEBUG &bat_attr_log_level, #endif diff --git a/batman-adv/gateway_client.c b/batman-adv/gateway_client.c index 56c52b0..fde1d8a 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -118,7 +118,7 @@ void gw_election(struct bat_priv *bat_priv)
switch (atomic_read(&bat_priv->gw_sel_class)) { case 1: /* fast connection */ - gw_srv_class_to_kbit(gw_node->orig_node->gw_flags, + gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
tmp_gw_factor = (gw_node->orig_node->router->tq_avg * @@ -247,7 +247,7 @@ static void gw_node_add(struct bat_priv *bat_priv, hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list); spin_unlock_bh(&bat_priv->gw_list_lock);
- gw_srv_class_to_kbit(new_gwflags, &down, &up); + gw_bandwidth_to_kbit(new_gwflags, &down, &up); bat_dbg(DBG_BATMAN, bat_priv, "Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n", orig_node->orig, new_gwflags, @@ -336,7 +336,7 @@ static int _write_buffer_text(struct bat_priv *bat_priv, { int down, up;
- gw_srv_class_to_kbit(gw_node->orig_node->gw_flags, &down, &up); + gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
return seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", (bat_priv->curr_gw == gw_node ? "=>" : " "), diff --git a/batman-adv/gateway_common.c b/batman-adv/gateway_common.c index 330167e..9d03e3c 100644 --- a/batman-adv/gateway_common.c +++ b/batman-adv/gateway_common.c @@ -24,7 +24,7 @@ #include "gateway_client.h"
/* calculates the gateway class from kbit */ -static void kbit_to_gw_srv_class(int down, int up, long *gw_srv_class) +static void kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class) { int mdown = 0, tdown, tup, difference; uint8_t sbit, part; @@ -59,7 +59,7 @@ static void kbit_to_gw_srv_class(int down, int up, long *gw_srv_class) }
/* returns the up and downspeeds in kbit, calculated from the class */ -void gw_srv_class_to_kbit(uint8_t gw_srv_class, int *down, int *up) +void gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up) { char sbit = (gw_srv_class & 0x80) >> 7; char dpart = (gw_srv_class & 0x78) >> 3; @@ -113,8 +113,7 @@ static bool parse_gw_mode_tok(struct net_device *net_dev, if (strnicmp(tmp_ptr, "mbit", 4) == 0) multi = 1024;
- if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || - (multi > 1)) + if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || (multi > 1)) *tmp_ptr = '\0'; }
@@ -253,14 +252,14 @@ next: if (!up) up = down / 5;
- kbit_to_gw_srv_class(down, up, &gw_class_tmp); + kbit_to_gw_bandwidth(down, up, &gw_class_tmp);
/** * the gw class we guessed above might not match the given * speeds, hence we need to calculate it back to show the * number that is going to be propagated **/ - gw_srv_class_to_kbit((uint8_t)gw_class_tmp, + gw_bandwidth_to_kbit((uint8_t)gw_class_tmp, (int *)&down, (int *)&up);
gw_deselect(bat_priv); @@ -271,6 +270,8 @@ next: (down > 2048 ? "MBit" : "KBit"), (up > 2048 ? up / 1024 : up), (up > 2048 ? "MBit" : "KBit")); + + atomic_set(&bat_priv->gw_bandwidth, gw_class_tmp); break; default: bat_info(net_dev, "Changing gateway mode from: '%s' to: '%s'\n", @@ -279,7 +280,6 @@ next: }
atomic_set(&bat_priv->gw_mode, gw_mode_tmp); - atomic_set(&bat_priv->gw_class, gw_class_tmp);
if (gw_class_tmp == 0) gw_deselect(bat_priv); @@ -287,3 +287,104 @@ next: end: return count; } + +static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, + long *up, long *down) +{ + int ret, multi = 1; + char *slash_ptr, *tmp_ptr; + + slash_ptr = strchr(buff, '/'); + if (slash_ptr) + *slash_ptr = 0; + + if (strlen(buff) > 4) { + tmp_ptr = buff + strlen(buff) - 4; + + if (strnicmp(tmp_ptr, "mbit", 4) == 0) + multi = 1024; + + if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || + (multi > 1)) + *tmp_ptr = '\0'; + } + + ret = strict_strtoul(buff, 10, down); + if (ret) { + bat_err(net_dev, + "Download speed of gateway mode invalid: %s\n", + buff); + return false; + } + + *down *= multi; + + /* we also got some upload info */ + if (slash_ptr) { + multi = 1; + + if (strlen(slash_ptr + 1) > 4) { + tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1); + + if (strnicmp(tmp_ptr, "mbit", 4) == 0) + multi = 1024; + + if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || + (multi > 1)) + *tmp_ptr = '\0'; + } + + ret = strict_strtoul(slash_ptr + 1, 10, up); + if (ret) { + bat_err(net_dev, + "Upload speed of gateway mode invalid: " + "%s\n", slash_ptr + 1); + return false; + } + + *up *= multi; + } + + return true; +} + +ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count) +{ + struct bat_priv *bat_priv = netdev_priv(net_dev); + long gw_bandwidth_tmp = 0, up = 0, down = 0; + bool ret; + + ret = parse_gw_bandwidth(net_dev, buff, &up, &down); + if (!ret) + goto end; + + if ((!down) || (down < 256)) + down = 2000; + + if (!up) + up = down / 5; + + kbit_to_gw_bandwidth(down, up, &gw_bandwidth_tmp); + + /** + * the gw bandwidth we guessed above might not match the given + * speeds, hence we need to calculate it back to show the number + * that is going to be propagated + **/ + gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, + (int *)&down, (int *)&up); + + gw_deselect(bat_priv); + bat_info(net_dev, "Changing gateway bandwidth from: '%i' to: '%ld' " + "(propagating: %ld%s/%ld%s)\n", + atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp, + (down > 2048 ? down / 1024 : down), + (down > 2048 ? "MBit" : "KBit"), + (up > 2048 ? up / 1024 : up), + (up > 2048 ? "MBit" : "KBit")); + + atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp); + +end: + return count; +} diff --git a/batman-adv/gateway_common.h b/batman-adv/gateway_common.h index 8074c70..181a306 100644 --- a/batman-adv/gateway_common.h +++ b/batman-adv/gateway_common.h @@ -32,7 +32,8 @@ enum gw_modes { #define GW_MODE_CLIENT_NAME "client" #define GW_MODE_SERVER_NAME "server"
-void gw_srv_class_to_kbit(uint8_t gw_class, int *down, int *up); +void gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up); ssize_t gw_mode_set(struct net_device *net_dev, char *buff, size_t count); +ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count);
#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */ diff --git a/batman-adv/send.c b/batman-adv/send.c index 454049c..b89b9f7 100644 --- a/batman-adv/send.c +++ b/batman-adv/send.c @@ -287,7 +287,7 @@ void schedule_own_packet(struct batman_if *batman_if) if ((batman_if == bat_priv->primary_if) && (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) batman_packet->gw_flags = - (uint8_t)atomic_read(&bat_priv->gw_class); + (uint8_t)atomic_read(&bat_priv->gw_bandwidth); else batman_packet->gw_flags = 0;
diff --git a/batman-adv/soft-interface.c b/batman-adv/soft-interface.c index 7b2673c..9561433 100644 --- a/batman-adv/soft-interface.c +++ b/batman-adv/soft-interface.c @@ -592,7 +592,7 @@ struct net_device *softif_create(char *name) atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); atomic_set(&bat_priv->gw_sel_class, 0); - atomic_set(&bat_priv->gw_class, 0); + atomic_set(&bat_priv->gw_bandwidth, 0); atomic_set(&bat_priv->orig_interval, 1000); atomic_set(&bat_priv->hop_penalty, 10); atomic_set(&bat_priv->log_level, 0); diff --git a/batman-adv/types.h b/batman-adv/types.h index b68add4..1d00849 100644 --- a/batman-adv/types.h +++ b/batman-adv/types.h @@ -129,7 +129,7 @@ struct bat_priv { atomic_t vis_mode; /* VIS_TYPE_* */ atomic_t gw_mode; /* GW_MODE_* */ atomic_t gw_sel_class; /* uint */ - atomic_t gw_class; /* uint */ + atomic_t gw_bandwidth; /* gw bandwidth */ atomic_t orig_interval; /* uint */ atomic_t hop_penalty; /* uint */ atomic_t log_level; /* uint */
The Linux kernel guidelines require each sysfs file to have a single value / purpose, therefore it is necessary to split up the sysfs gateway files.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- batman-adv/bat_sysfs.c | 70 ++++++++++---- batman-adv/gateway_common.c | 213 ------------------------------------------- batman-adv/gateway_common.h | 1 - batman-adv/soft-interface.c | 4 +- 4 files changed, 53 insertions(+), 235 deletions(-)
diff --git a/batman-adv/bat_sysfs.c b/batman-adv/bat_sysfs.c index f937f6f..cd7bb51 100644 --- a/batman-adv/bat_sysfs.c +++ b/batman-adv/bat_sysfs.c @@ -261,30 +261,17 @@ static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr, char *buff) { struct bat_priv *bat_priv = kobj_to_batpriv(kobj); - int down, up, bytes_written; - int gw_class, gw_mode = atomic_read(&bat_priv->gw_mode); + int bytes_written;
- switch (gw_mode) { + switch (atomic_read(&bat_priv->gw_mode)) { case GW_MODE_CLIENT: - gw_class = atomic_read(&bat_priv->gw_sel_class); - bytes_written = sprintf(buff, "%s (gw_class: %i)\n", - GW_MODE_CLIENT_NAME, gw_class); + bytes_written = sprintf(buff, "%s\n", GW_MODE_CLIENT_NAME); break; case GW_MODE_SERVER: - gw_class = atomic_read(&bat_priv->gw_bandwidth); - gw_bandwidth_to_kbit(gw_class, &down, &up); - bytes_written = sprintf(buff, - "%s (gw_class: %i " - "-> propagating: %i%s/%i%s)\n", - GW_MODE_SERVER_NAME, gw_class, - (down > 2048 ? down / 1024 : down), - (down > 2048 ? "MBit" : "KBit"), - (up > 2048 ? up / 1024 : up), - (up > 2048 ? "MBit" : "KBit")); + bytes_written = sprintf(buff, "%s\n", GW_MODE_SERVER_NAME); break; default: - bytes_written = sprintf(buff, "%s\n", - GW_MODE_OFF_NAME); + bytes_written = sprintf(buff, "%s\n", GW_MODE_OFF_NAME); break; }
@@ -295,7 +282,52 @@ static ssize_t store_gw_mode(struct kobject *kobj, struct attribute *attr, char *buff, size_t count) { struct net_device *net_dev = kobj_to_netdev(kobj); - return gw_mode_set(net_dev, buff, count); + struct bat_priv *bat_priv = netdev_priv(net_dev); + char *curr_gw_mode_str; + int gw_mode_tmp = -1; + + if (buff[count - 1] == '\n') + buff[count - 1] = '\0'; + + if (strncmp(buff, GW_MODE_OFF_NAME, strlen(GW_MODE_OFF_NAME)) == 0) + gw_mode_tmp = GW_MODE_OFF; + + if (strncmp(buff, GW_MODE_CLIENT_NAME, + strlen(GW_MODE_CLIENT_NAME)) == 0) + gw_mode_tmp = GW_MODE_CLIENT; + + if (strncmp(buff, GW_MODE_SERVER_NAME, + strlen(GW_MODE_SERVER_NAME)) == 0) + gw_mode_tmp = GW_MODE_SERVER; + + if (gw_mode_tmp < 0) { + bat_info(net_dev, + "Invalid parameter for 'gw mode' setting received: " + "%s\n", buff); + return -EINVAL; + } + + if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp) + return count; + + switch (atomic_read(&bat_priv->gw_mode)) { + case GW_MODE_CLIENT: + curr_gw_mode_str = GW_MODE_CLIENT_NAME; + break; + case GW_MODE_SERVER: + curr_gw_mode_str = GW_MODE_SERVER_NAME; + break; + default: + curr_gw_mode_str = GW_MODE_OFF_NAME; + break; + } + + bat_info(net_dev, "Changing gw mode from: %s to: %s\n", + curr_gw_mode_str, buff); + + gw_deselect(bat_priv); + atomic_set(&bat_priv->gw_mode, (unsigned)gw_mode_tmp); + return count; }
static ssize_t show_gw_bwidth(struct kobject *kobj, struct attribute *attr, diff --git a/batman-adv/gateway_common.c b/batman-adv/gateway_common.c index 9d03e3c..b962982 100644 --- a/batman-adv/gateway_common.c +++ b/batman-adv/gateway_common.c @@ -75,219 +75,6 @@ void gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up) *up = ((upart + 1) * (*down)) / 8; }
-static bool parse_gw_mode_tok(struct net_device *net_dev, - char *tokptr, long *gw_mode_tmp, - char **gw_mode_tmp_str, long *gw_class_tmp, - long *up, long *down) -{ - int ret, multi; - char *slash_ptr, *tmp_ptr; - - switch (*gw_mode_tmp) { - case GW_MODE_CLIENT: - ret = strict_strtoul(tokptr, 10, gw_class_tmp); - if (ret) { - bat_err(net_dev, "Client class of gateway mode invalid:" - " %s\n", tokptr); - return false; - } - - if (*gw_class_tmp > TQ_MAX_VALUE) { - bat_err(net_dev, - "Client class of gateway mode greater than %i: " - "%ld\n", TQ_MAX_VALUE, *gw_class_tmp); - return false; - } - - break; - case GW_MODE_SERVER: - slash_ptr = strchr(tokptr, '/'); - if (slash_ptr) - *slash_ptr = 0; - - multi = 1; - - if (strlen(tokptr) > 4) { - tmp_ptr = tokptr + strlen(tokptr) - 4; - - if (strnicmp(tmp_ptr, "mbit", 4) == 0) - multi = 1024; - - if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || (multi > 1)) - *tmp_ptr = '\0'; - } - - ret = strict_strtoul(tokptr, 10, down); - if (ret) { - bat_err(net_dev, - "Download speed of gateway mode invalid: %s\n", - tokptr); - return false; - } - - *down *= multi; - - /* we also got some upload info */ - if (slash_ptr) { - multi = 1; - - if (strlen(slash_ptr + 1) > 4) { - tmp_ptr = slash_ptr + 1 - 4 - + strlen(slash_ptr + 1); - - if (strnicmp(tmp_ptr, "mbit", 4) == 0) - multi = 1024; - - if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || - (multi > 1)) - *tmp_ptr = '\0'; - } - - ret = strict_strtoul(slash_ptr + 1, 10, up); - if (ret) { - bat_err(net_dev, - "Upload speed of gateway mode invalid: " - "%s\n", slash_ptr + 1); - return false; - } - - *up *= multi; - } - - break; - default: - if (strcmp(tokptr, GW_MODE_OFF_NAME) == 0) { - *gw_mode_tmp = GW_MODE_OFF; - *gw_mode_tmp_str = GW_MODE_OFF_NAME; - } - - if (strcmp(tokptr, GW_MODE_CLIENT_NAME) == 0) { - *gw_mode_tmp = GW_MODE_CLIENT; - *gw_mode_tmp_str = GW_MODE_CLIENT_NAME; - } - - if (strcmp(tokptr, GW_MODE_SERVER_NAME) == 0) { - *gw_mode_tmp = GW_MODE_SERVER; - *gw_mode_tmp_str = GW_MODE_SERVER_NAME; - } - } - - return true; -} - -ssize_t gw_mode_set(struct net_device *net_dev, char *buff, size_t count) -{ - char *tokptr, *cp, finished; - char *gw_mode_curr_str, *gw_mode_tmp_str = NULL; - long gw_mode_curr, gw_mode_tmp = GW_MODE_OFF; - long gw_class_tmp = 0, up = 0, down = 0; - bool ret; - struct bat_priv *bat_priv = netdev_priv(net_dev); - - tokptr = buff; - gw_mode_curr = atomic_read(&bat_priv->gw_mode); - - for (cp = buff, finished = 0; !finished; cp++) { - switch (*cp) { - case 0: - finished = 1; - case ' ': - case '\n': - case '\t': - *cp = 0; - - if (strlen(tokptr) == 0) - goto next; - - ret = parse_gw_mode_tok(net_dev, tokptr, &gw_mode_tmp, - &gw_mode_tmp_str, &gw_class_tmp, - &up, &down); - - if (!ret) - goto end; - -next: - tokptr = cp + 1; - break; - default: - break; - } - } - - if (!gw_mode_tmp_str) { - bat_info(net_dev, "Gateway mode can only be set to: '%s', '%s' " - "or '%s' - given value: %s\n", GW_MODE_OFF_NAME, - GW_MODE_CLIENT_NAME, GW_MODE_SERVER_NAME, buff); - goto end; - } - - switch (gw_mode_curr) { - case GW_MODE_CLIENT: - gw_mode_curr_str = GW_MODE_CLIENT_NAME; - break; - case GW_MODE_SERVER: - gw_mode_curr_str = GW_MODE_SERVER_NAME; - break; - default: - gw_mode_curr_str = GW_MODE_OFF_NAME; - break; - } - - switch (gw_mode_tmp) { - case GW_MODE_CLIENT: - gw_class_tmp = atomic_read(&bat_priv->gw_sel_class); - if ((gw_mode_tmp == GW_MODE_CLIENT) && (!gw_class_tmp)) - gw_class_tmp = 20; - - bat_info(net_dev, "Changing gateway mode from: '%s' to: '%s' " - "(gw_sel_class: %ld)\n", - gw_mode_curr_str, gw_mode_tmp_str, gw_class_tmp); - - atomic_set(&bat_priv->gw_sel_class, gw_class_tmp); - break; - case GW_MODE_SERVER: - if (!down) - down = 2000; - - if (!up) - up = down / 5; - - kbit_to_gw_bandwidth(down, up, &gw_class_tmp); - - /** - * the gw class we guessed above might not match the given - * speeds, hence we need to calculate it back to show the - * number that is going to be propagated - **/ - gw_bandwidth_to_kbit((uint8_t)gw_class_tmp, - (int *)&down, (int *)&up); - - gw_deselect(bat_priv); - bat_info(net_dev, "Changing gateway mode from: '%s' to: '%s' " - "(gw_class: %ld -> propagating: %ld%s/%ld%s)\n", - gw_mode_curr_str, gw_mode_tmp_str, gw_class_tmp, - (down > 2048 ? down / 1024 : down), - (down > 2048 ? "MBit" : "KBit"), - (up > 2048 ? up / 1024 : up), - (up > 2048 ? "MBit" : "KBit")); - - atomic_set(&bat_priv->gw_bandwidth, gw_class_tmp); - break; - default: - bat_info(net_dev, "Changing gateway mode from: '%s' to: '%s'\n", - gw_mode_curr_str, gw_mode_tmp_str); - break; - } - - atomic_set(&bat_priv->gw_mode, gw_mode_tmp); - - if (gw_class_tmp == 0) - gw_deselect(bat_priv); - -end: - return count; -} - static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, long *up, long *down) { diff --git a/batman-adv/gateway_common.h b/batman-adv/gateway_common.h index 181a306..5e728d0 100644 --- a/batman-adv/gateway_common.h +++ b/batman-adv/gateway_common.h @@ -33,7 +33,6 @@ enum gw_modes { #define GW_MODE_SERVER_NAME "server"
void gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up); -ssize_t gw_mode_set(struct net_device *net_dev, char *buff, size_t count); ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count);
#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */ diff --git a/batman-adv/soft-interface.c b/batman-adv/soft-interface.c index 9561433..1e55bdb 100644 --- a/batman-adv/soft-interface.c +++ b/batman-adv/soft-interface.c @@ -591,8 +591,8 @@ struct net_device *softif_create(char *name) atomic_set(&bat_priv->bonding, 0); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); - atomic_set(&bat_priv->gw_sel_class, 0); - atomic_set(&bat_priv->gw_bandwidth, 0); + 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, 10); atomic_set(&bat_priv->log_level, 0);
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- batctl/main.c | 3 +- batctl/man/batctl.8 | 4 +- batctl/sys.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++- batctl/sys.h | 9 ++++ 4 files changed, 128 insertions(+), 5 deletions(-)
diff --git a/batctl/main.c b/batctl/main.c index 9c1195b..850959a 100644 --- a/batctl/main.c +++ b/batctl/main.c @@ -166,8 +166,7 @@ int main(int argc, char **argv)
} else if ((strcmp(argv[1], "gw_mode") == 0) || (strcmp(argv[1], "gw") == 0)) {
- ret = handle_sys_setting(mesh_iface, argc - 1, argv + 1, - SYS_GW_MODE, gw_mode_usage, sysfs_param_server); + ret = handle_gw_setting(mesh_iface, argc - 1, argv + 1);
} else if ((strcmp(argv[1], "gateways") == 0) || (strcmp(argv[1], "gwl") == 0)) {
diff --git a/batctl/man/batctl.8 b/batctl/man/batctl.8 index 13822ef..ba2d32d 100644 --- a/batctl/man/batctl.8 +++ b/batctl/man/batctl.8 @@ -70,8 +70,8 @@ If no parameter is given the current log level settings are displayed otherwise .IP "\fBlog\fP|\fBl\fP [\fB-n\fP]\fP" batctl will read the batman-adv debug log which has to be compiled into the kernel module. If "-n" is given batctl will not replace the MAC addresses with bat-host names in the output. .br -.IP "\fBgw_mode|gw\fP [\fBoff\fP|\fBclient\fP|\fBserver\fP] [\fBgw_class\fP]\fP" -If no parameter is given the current gateway mode is displayed otherwise the parameter is used to set the gateway mode. The second (optional) argument specifies the gateway class. Its function depends on whether the node is a server or a client. If the node is a server this parameter is used to inform other nodes in the network about this node's internet connection bandwidth. Just enter any number (optionally followed by "kbit" or "mbit") and the batman-adv module will guess your appropriate gateway class. Use "/" to separate the down(hy and upload rates. You can omit the upload rate and the module will assume an upload of download / 5. +.IP "\fBgw_mode|gw\fP [\fBoff\fP|\fBclient\fP|\fBserver\fP] [\fBsel_class|bandwidth\fP]\fP" +If no parameter is given the current gateway mode is displayed otherwise the parameter is used to set the gateway mode. The second (optional) argument specifies the selection class (if 'client' was the first argument) or the gateway bandwidth (if 'server' was the first argument). If the node is a server this parameter is used to inform other nodes in the network about this node's internet connection bandwidth. Just enter any number (optionally followed by "kbit" or "mbit") and the batman-adv module will guess your appropriate gateway class. Use "/" to separate the down(hy and upload rates. You can omit the upload rate and the module will assume an upload of download / 5. .RS 17 default: 2000 -> gateway class 20 .RE diff --git a/batctl/sys.c b/batctl/sys.c index 79d9612..bb976c0 100644 --- a/batctl/sys.c +++ b/batctl/sys.c @@ -241,7 +241,7 @@ void bonding_usage(void)
void gw_mode_usage(void) { - printf("Usage: batctl [options] gw_mode [mode]\n"); + printf("Usage: batctl [options] gw_mode [mode] [sel_class|bandwidth]\n"); printf("options:\n"); printf(" \t -h print this help\n"); } @@ -323,3 +323,118 @@ out: free(path_buff); return res; } + +int handle_gw_setting(char *mesh_iface, int argc, char **argv) +{ + int optchar, res = EXIT_FAILURE; + char *path_buff, gw_mode; + const char **ptr; + + while ((optchar = getopt(argc, argv, "h")) != -1) { + switch (optchar) { + case 'h': + gw_mode_usage(); + return EXIT_SUCCESS; + default: + gw_mode_usage(); + return EXIT_FAILURE; + } + } + + path_buff = malloc(PATH_BUFF_LEN); + snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, mesh_iface); + + if (argc == 1) { + res = read_file(path_buff, SYS_GW_MODE, SINGLE_READ | USE_READ_BUFF, 0, 0); + + if (res != EXIT_SUCCESS) + goto out; + + if (line_ptr[strlen(line_ptr) - 1] == '\n') + line_ptr[strlen(line_ptr) - 1] = '\0'; + + if (strcmp(line_ptr, "client") == 0) + gw_mode = GW_MODE_CLIENT; + else if (strcmp(line_ptr, "server") == 0) + gw_mode = GW_MODE_SERVER; + else + gw_mode = GW_MODE_OFF; + + free(line_ptr); + line_ptr = NULL; + + switch (gw_mode) { + case GW_MODE_CLIENT: + res = read_file(path_buff, SYS_GW_SEL, SINGLE_READ | USE_READ_BUFF, 0, 0); + break; + case GW_MODE_SERVER: + res = read_file(path_buff, SYS_GW_BW, SINGLE_READ | USE_READ_BUFF, 0, 0); + break; + default: + printf("off\n"); + goto out; + } + + if (res != EXIT_SUCCESS) + goto out; + + if (line_ptr[strlen(line_ptr) - 1] == '\n') + line_ptr[strlen(line_ptr) - 1] = '\0'; + + switch (gw_mode) { + case GW_MODE_CLIENT: + printf("client (selection class: %s)\n", line_ptr); + break; + case GW_MODE_SERVER: + printf("server (announced bw: %s)\n", line_ptr); + break; + default: + goto out; + } + + free(line_ptr); + line_ptr = NULL; + goto out; + } + + if (strcmp(argv[1], "client") == 0) + gw_mode = GW_MODE_CLIENT; + else if (strcmp(argv[1], "server") == 0) + gw_mode = GW_MODE_SERVER; + else if (strcmp(argv[1], "off") == 0) + gw_mode = GW_MODE_OFF; + else + goto opt_err; + + res = write_file(path_buff, SYS_GW_MODE, argv[1], NULL); + if (res != EXIT_SUCCESS) + goto out; + + if (argc == 2) + goto out; + + switch (gw_mode) { + case GW_MODE_CLIENT: + res = write_file(path_buff, SYS_GW_SEL, argv[2], NULL); + break; + case GW_MODE_SERVER: + res = write_file(path_buff, SYS_GW_BW, argv[2], NULL); + break; + default: + goto out; + } + +opt_err: + printf("Error - the supplied argument is invalid: %s\n", argv[1]); + printf("The following values are allowed:\n"); + + ptr = sysfs_param_server; + while (*ptr) { + printf(" * %s\n", *ptr); + ptr++; + } + +out: + free(path_buff); + return res; +} diff --git a/batctl/sys.h b/batctl/sys.h index 71362f1..066b8bd 100644 --- a/batctl/sys.h +++ b/batctl/sys.h @@ -26,6 +26,8 @@ #define SYS_AGGR "aggregated_ogms" #define SYS_BONDING "bonding" #define SYS_GW_MODE "gw_mode" +#define SYS_GW_SEL "gw_sel_class" +#define SYS_GW_BW "gw_bandwidth" #define SYS_VIS_MODE "vis_mode" #define SYS_ORIG_INTERVAL "orig_interval" #define SYS_IFACE_PATH "/sys/class/net" @@ -33,6 +35,12 @@ #define SYS_IFACE_STATUS_FMT SYS_IFACE_PATH"/%s/batman_adv/iface_status" #define SYS_FRAG "fragmentation"
+enum gw_modes { + GW_MODE_OFF, + GW_MODE_CLIENT, + GW_MODE_SERVER, +}; + extern const char *sysfs_param_enable[]; extern const char *sysfs_param_server[];
@@ -47,3 +55,4 @@ int handle_loglevel(char *mesh_iface, int argc, char **argv); int handle_sys_setting(char *mesh_iface, int argc, char **argv, char *file_path, void setting_usage(void), const char *sysfs_param[]); +int handle_gw_setting(char *mesh_iface, int argc, char **argv);
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- batman-adv/sysfs-class-net-mesh | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/batman-adv/sysfs-class-net-mesh b/batman-adv/sysfs-class-net-mesh index bd20e14..748fe17 100644 --- a/batman-adv/sysfs-class-net-mesh +++ b/batman-adv/sysfs-class-net-mesh @@ -22,6 +22,27 @@ Description: mesh will be fragmented or silently discarded if the packet size exceeds the outgoing interface MTU.
+What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth +Date: October 2010 +Contact: Marek Lindner lindner_marek@yahoo.de +Description: + Defines the bandwidth which is propagated by this + node if gw_mode was set to 'server'. + +What: /sys/class/net/<mesh_iface>/mesh/gw_mode +Date: October 2010 +Contact: Marek Lindner lindner_marek@yahoo.de +Description: + Defines the state of the gateway features. Can be + either 'off', 'client' or 'server'. + +What: /sys/class/net/<mesh_iface>/mesh/gw_sel_class +Date: October 2010 +Contact: Marek Lindner lindner_marek@yahoo.de +Description: + Defines the selection criteria this node will use + to choose a gateway if gw_mode was set to 'client'. + What: /sys/class/net/<mesh_iface>/mesh/orig_interval Date: May 2010 Contact: Marek Lindner lindner_marek@yahoo.de
Some additional checks will be needed in case of extension headers like the fragmentation or hop-by-hop (for jumbo frames for example) headers or ipsec stuff. But this patch should do for most people for now, the rest can be added with a later one.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Acked-by: Linus Lüssing linus.luessing@web.de --- batman-adv/gateway_client.c | 40 +++++++++++++++++++++++++++++++--------- 1 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/batman-adv/gateway_client.c b/batman-adv/gateway_client.c index fde1d8a..0065ffb 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -24,6 +24,7 @@ #include "gateway_common.h" #include "hard-interface.h" #include <linux/ip.h> +#include <linux/ipv6.h> #include <linux/udp.h> #include <linux/if_vlan.h>
@@ -403,6 +404,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) { struct ethhdr *ethhdr; struct iphdr *iphdr; + struct ipv6hdr *ipv6hdr; struct udphdr *udphdr; unsigned int header_len = 0;
@@ -424,17 +426,32 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) }
/* check for ip header */ - if (ntohs(ethhdr->h_proto) != ETH_P_IP) - return 0; + switch (ntohs(ethhdr->h_proto)) { + case ETH_P_IP: + if (!pskb_may_pull(skb, header_len + sizeof(struct iphdr))) + return 0; + iphdr = (struct iphdr *)(skb->data + header_len); + header_len += iphdr->ihl * 4;
- if (!pskb_may_pull(skb, header_len + sizeof(struct iphdr))) - return 0; - iphdr = (struct iphdr *)(skb->data + header_len); - header_len += iphdr->ihl * 4; + /* check for udp header */ + if (iphdr->protocol != IPPROTO_UDP) + return 0; + + break; + case ETH_P_IPV6: + if (!pskb_may_pull(skb, header_len + sizeof(struct ipv6hdr))) + return 0; + ipv6hdr = (struct ipv6hdr *)(skb->data + header_len); + header_len += sizeof(struct ipv6hdr);
- /* check for udp header */ - if (iphdr->protocol != IPPROTO_UDP) + /* check for udp header */ + if (ipv6hdr->nexthdr != IPPROTO_UDP) + return 0; + + break; + default: return 0; + }
if (!pskb_may_pull(skb, header_len + sizeof(struct udphdr))) return 0; @@ -442,7 +459,12 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) header_len += sizeof(struct udphdr);
/* check for bootp port */ - if (ntohs(udphdr->dest) != 67) + if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && + (ntohs(udphdr->dest) != 67)) + return 0; + + if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && + (ntohs(udphdr->dest) != 547)) return 0;
if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)
b.a.t.m.a.n@lists.open-mesh.org