Hi,
the batman-adv gateway functionality has been available in the trunk for quite some time but was never able to enter an official release because the sysfs API did not follow the Linux kernel guidelines. I wrote a series of patches meant to address these style issues. A comprehensive documentation of the gateway handling is on my todo list and will follow shortly.
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 ac33c09..1cd7e0a 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -306,7 +306,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; @@ -315,32 +315,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_after(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 73d2752..6d6df7e 100644 --- a/batman-adv/main.c +++ b/batman-adv/main.c @@ -133,7 +133,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 8c72a40..39f3160 100644 --- a/batman-adv/originator.c +++ b/batman-adv/originator.c @@ -294,7 +294,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 1cd7e0a..6c6a0b3 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -400,54 +400,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 a13276b..25564c3 100644 --- a/batman-adv/soft-interface.c +++ b/batman-adv/soft-interface.c @@ -349,7 +349,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; @@ -380,14 +380,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 e85a922..34a69be 100644 --- a/batman-adv/bat_sysfs.c +++ b/batman-adv/bat_sysfs.c @@ -252,6 +252,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) { @@ -262,6 +268,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; @@ -299,6 +306,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 @@ -311,6 +320,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 6c6a0b3..4217b6b 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -117,7 +117,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); @@ -216,8 +216,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 3851930..05efe43 100644 --- a/batman-adv/gateway_common.c +++ b/batman-adv/gateway_common.c @@ -237,12 +237,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 3b03e2a..affc15f 100644 --- a/batman-adv/routing.c +++ b/batman-adv/routing.c @@ -33,6 +33,7 @@ #include "vis.h" #include "aggregation.h" #include "compat.h" +#include "gateway_common.h" #include "gateway_client.h" #include "unicast.h"
@@ -331,7 +332,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 25564c3..d737f76 100644 --- a/batman-adv/soft-interface.c +++ b/batman-adv/soft-interface.c @@ -593,6 +593,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 | 112 +++++++++++++++++++++++++++++++++++++++++-- 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, 148 insertions(+), 16 deletions(-)
diff --git a/batman-adv/bat_sysfs.c b/batman-adv/bat_sysfs.c index 34a69be..436b8da 100644 --- a/batman-adv/bat_sysfs.c +++ b/batman-adv/bat_sysfs.c @@ -263,8 +263,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: @@ -273,7 +272,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", @@ -293,12 +293,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); @@ -308,6 +334,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 @@ -321,6 +349,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 4217b6b..e6cd9ac 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -119,7 +119,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 * @@ -248,7 +248,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, @@ -337,7 +337,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 05efe43..fc197be 100644 --- a/batman-adv/gateway_common.c +++ b/batman-adv/gateway_common.c @@ -25,7 +25,7 @@ #include "compat.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; @@ -60,7 +60,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; @@ -254,14 +254,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); @@ -272,6 +272,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", @@ -280,7 +282,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); @@ -288,3 +289,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 a96a786..1bfbad3 100644 --- a/batman-adv/send.c +++ b/batman-adv/send.c @@ -289,7 +289,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 d737f76..e05f62e 100644 --- a/batman-adv/soft-interface.c +++ b/batman-adv/soft-interface.c @@ -594,7 +594,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 | 78 ++++++++++++---- batman-adv/gateway_common.c | 214 ------------------------------------------- batman-adv/gateway_common.h | 1 - 3 files changed, 59 insertions(+), 234 deletions(-)
diff --git a/batman-adv/bat_sysfs.c b/batman-adv/bat_sysfs.c index 436b8da..bac2ff0 100644 --- a/batman-adv/bat_sysfs.c +++ b/batman-adv/bat_sysfs.c @@ -262,30 +262,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; }
@@ -296,7 +283,60 @@ 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); + + if ((gw_mode_tmp == GW_MODE_CLIENT) && + (atomic_read(&bat_priv->gw_sel_class) == 0)) + atomic_set(&bat_priv->gw_sel_class, 20); + + if ((gw_mode_tmp == GW_MODE_SERVER) && + (atomic_read(&bat_priv->gw_bandwidth) == 0)) + atomic_set(&bat_priv->gw_bandwidth, 41); + + 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 fc197be..c71420d 100644 --- a/batman-adv/gateway_common.c +++ b/batman-adv/gateway_common.c @@ -76,220 +76,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_ */
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
Signed-off-by: Marek Lindner lindner_marek@yahoo.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 e6cd9ac..128f851 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -25,6 +25,7 @@ #include "hard-interface.h" #include "compat.h" #include <linux/ip.h> +#include <linux/ipv6.h> #include <linux/udp.h> #include <linux/if_vlan.h>
@@ -404,6 +405,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;
@@ -425,17 +427,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; @@ -443,7 +460,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)
Acked-by: Linus Lüssing linus.luessing@web.de
Just gave it a go on a basic dhcpv6 setup and works fine. Though 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.
Cheers, Linus
On Sun, Oct 24, 2010 at 03:14:23AM +0200, Marek Lindner wrote:
Signed-off-by: Marek Lindner lindner_marek@yahoo.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 e6cd9ac..128f851 100644 --- a/batman-adv/gateway_client.c +++ b/batman-adv/gateway_client.c @@ -25,6 +25,7 @@ #include "hard-interface.h" #include "compat.h" #include <linux/ip.h> +#include <linux/ipv6.h> #include <linux/udp.h> #include <linux/if_vlan.h>
@@ -404,6 +405,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;
@@ -425,17 +427,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;
@@ -443,7 +460,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)
-- 1.7.1
[PATCH 1/8] batman-adv: remove redundant gw_node_list_free() function
@@ -315,32 +315,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_after(jiffies, gw_node->deleted + timeout))) &&
atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)
continue;
This should be time_before.
[PATCH 4/8] batman-adv: move gateway bandwidth into its own sysfs file
@@ -293,12 +293,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)
Why was the space removed?
if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
(multi > 1))
Why this indentation? And This should be on a single line (or I count wrong).
[PATCH 5/8] batman-adv: cleanup gw mode sysfs file to only accept one value
if ((gw_mode_tmp == GW_MODE_CLIENT) &&
(atomic_read(&bat_priv->gw_sel_class) == 0))
atomic_set(&bat_priv->gw_sel_class, 20);
if ((gw_mode_tmp == GW_MODE_SERVER) &&
(atomic_read(&bat_priv->gw_bandwidth) == 0))
atomic_set(&bat_priv->gw_bandwidth, 41);
Why setting that here? And why do you set gw_sel_class here to 20 (if it is 0 before) and in softif_create to 0? Shouldn't it be set to 20 in softif_create instead?
I don't see a big problem at the moment.
Best regards, Sven
On Saturday 30 October 2010 14:14:02 Sven Eckelmann wrote:
struct gw_node *gw_node;
struct hlist_node *node, *node_tmp;
&bat_priv->gw_list, list) {
if (((!gw_node->deleted) ||
(time_after(jiffies, gw_node->deleted + timeout)))
&& + atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) + continue;
This should be time_before.
Agreed.
char *buff, size_t count)
char *buff, size_t count)
Why was the space removed?
Should I move this into a separate patch ?
if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
(multi > 1))
Why this indentation? And This should be on a single line (or I count wrong).
No, you are right. Will be fixed.
if ((gw_mode_tmp == GW_MODE_CLIENT) &&
(atomic_read(&bat_priv->gw_sel_class) == 0))
atomic_set(&bat_priv->gw_sel_class, 20);
if ((gw_mode_tmp == GW_MODE_SERVER) &&
(atomic_read(&bat_priv->gw_bandwidth) == 0))
atomic_set(&bat_priv->gw_bandwidth, 41);
Why setting that here? And why do you set gw_sel_class here to 20 (if it is 0 before) and in softif_create to 0? Shouldn't it be set to 20 in softif_create instead?
The general idea was that if somebody activated client or gateway mode without setting gw_sel_class or gw_bandwidth to any value, it would use some default values. Moving these checks into softif_create() would only solve half of the problem because a user could set these variables to 0 and then start the client or server. At least the client mode requires the gw_sel_class variable value to be greater than 0.
Thanks for the comments, Marek
Marek Lindner wrote:
char *buff, size_t count)
char *buff, size_t count)
Why was the space removed?
Should I move this into a separate patch ?
Sry, my fault. just forget it :)
if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
(multi > 1))
Why this indentation? And This should be on a single line (or I count wrong).
No, you are right. Will be fixed.
if ((gw_mode_tmp == GW_MODE_CLIENT) &&
(atomic_read(&bat_priv->gw_sel_class) == 0))
atomic_set(&bat_priv->gw_sel_class, 20);
if ((gw_mode_tmp == GW_MODE_SERVER) &&
(atomic_read(&bat_priv->gw_bandwidth) == 0))
atomic_set(&bat_priv->gw_bandwidth, 41);
Why setting that here? And why do you set gw_sel_class here to 20 (if it is 0 before) and in softif_create to 0? Shouldn't it be set to 20 in softif_create instead?
The general idea was that if somebody activated client or gateway mode without setting gw_sel_class or gw_bandwidth to any value, it would use some default values. Moving these checks into softif_create() would only solve half of the problem because a user could set these variables to 0 and then start the client or server. At least the client mode requires the gw_sel_class variable value to be greater than 0.
Isn't it limited to 1 by BAT_ATTR_UINT? And if not (which I doubt) wouldn't be the user still be able to set it to 0 after he changed it to client mode?
Best regards, Sven
On Sunday 31 October 2010 16:55:40 Sven Eckelmann wrote:
Isn't it limited to 1 by BAT_ATTR_UINT? And if not (which I doubt) wouldn't be the user still be able to set it to 0 after he changed it to client mode?
You got a point here. I'll come up with another solution.
Cheers, Marek
b.a.t.m.a.n@lists.open-mesh.org