@@ -118,6 +118,7 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
batadv_ogm_packet->header.ttl = 2;
batadv_ogm_packet->flags = BATADV_NO_FLAGS;
+ batadv_ogm_packet->reserved = 0;
batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
batadv_ogm_packet->tt_num_changes = 0;
batadv_ogm_packet->ttvn = 0;
@@ -639,7 +640,6 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
int vis_server, tt_num_changes = 0;
uint32_t seqno;
- uint8_t bandwidth;
uint16_t tvlv_len = 0;
vis_server = atomic_read(&bat_priv->vis_mode);
@@ -668,14 +668,6 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
else
batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER;
- if (hard_iface == primary_if &&
- atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) {
- bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
- batadv_ogm_packet->gw_flags = bandwidth;
- } else {
- batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS;
- }
-
batadv_slide_own_bcast_window(hard_iface);
batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
@@ -810,19 +802,6 @@ update_tt:
batadv_ogm_packet->tt_num_changes,
batadv_ogm_packet->ttvn,
ntohs(batadv_ogm_packet->tt_crc));
-
- if (orig_node->gw_flags != batadv_ogm_packet->gw_flags)
- batadv_gw_node_update(bat_priv, orig_node,
- batadv_ogm_packet->gw_flags);
-
- orig_node->gw_flags = batadv_ogm_packet->gw_flags;
-
- /* restart gateway selection if fast or late switching was enabled */
- if ((orig_node->gw_flags) &&
- (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) &&
- (atomic_read(&bat_priv->gw_sel_class) > 2))
- batadv_gw_check_election(bat_priv, orig_node);
-
goto out;
unlock:
@@ -20,6 +20,7 @@
#include "main.h"
#include "gateway_common.h"
#include "gateway_client.h"
+#include "packet.h"
/* calculates the gateway class from kbit */
static void batadv_kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class)
@@ -134,6 +135,31 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
return true;
}
+/**
+ * batadv_gw_tvlv_container_update - update the gw tvlv container after gateway
+ * setting change
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv)
+{
+ char gw_mode, gw_tvlv_value;
+
+ gw_mode = atomic_read(&bat_priv->gw_mode);
+
+ switch (gw_mode) {
+ case BATADV_GW_MODE_OFF:
+ case BATADV_GW_MODE_CLIENT:
+ batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1);
+ break;
+ case BATADV_GW_MODE_SERVER:
+ gw_tvlv_value = atomic_read(&bat_priv->gw_bandwidth);
+ batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1,
+ &gw_tvlv_value,
+ sizeof(gw_tvlv_value));
+ break;
+ }
+}
+
ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
size_t count)
{
@@ -173,7 +199,67 @@ ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
(up > 2048 ? "MBit" : "KBit"));
atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp);
+ batadv_gw_tvlv_container_update(bat_priv);
end:
return count;
}
+
+/**
+ * batadv_gw_tvlv_ogm_handler_v1 - process incoming gateway tvlv container
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig: the orig_node of the ogm
+ * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
+ * @tvlv_value: tvlv buffer containing the gateway data
+ * @tvlv_value_len: tvlv buffer length
+ */
+static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
+ struct batadv_orig_node *orig,
+ uint8_t flags,
+ void *tvlv_value,
+ uint16_t tvlv_value_len)
+{
+ uint8_t gw_flags = BATADV_NO_FLAGS;
+
+ /* only fetch the tvlv value if the handler wasn't called via the
+ * CIFNOTFND flag and if there is data to fetch
+ */
+ if (!(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) &&
+ (tvlv_value) && (tvlv_value_len == 1))
+ gw_flags = *(unsigned char *)tvlv_value;
+
+ if (orig->gw_flags != gw_flags)
+ batadv_gw_node_update(bat_priv, orig, gw_flags);
+
+ orig->gw_flags = gw_flags;
+
+ /* restart gateway selection if fast or late switching was enabled */
+ if ((orig->gw_flags != BATADV_NO_FLAGS) &&
+ (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) &&
+ (atomic_read(&bat_priv->gw_sel_class) > 2))
+ batadv_gw_check_election(bat_priv, orig);
+}
+
+/**
+ * batadv_gw_init - initialise the gateway handling internals
+ * @bat_priv: the bat priv with all the soft interface information
+ *
+ * Return 0 on success or negative error number in case of failure.
+ */
+int batadv_gw_init(struct batadv_priv *bat_priv)
+{
+ batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1,
+ NULL, BATADV_TVLV_GW, 1,
+ BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
+ return 0;
+}
+
+/**
+ * batadv_gw_free - free the gateway handling internals
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_gw_free(struct batadv_priv *bat_priv)
+{
+ batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1);
+ batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1);
+}
@@ -33,5 +33,8 @@ enum batadv_gw_modes {
void batadv_gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up);
ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
size_t count);
+void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv);
+int batadv_gw_init(struct batadv_priv *bat_priv);
+void batadv_gw_free(struct batadv_priv *bat_priv);
#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */
@@ -33,6 +33,7 @@
#include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h"
#include "unicast.h"
+#include "gateway_common.h"
#include "vis.h"
#include "hash.h"
#include "bat_algo.h"
@@ -147,6 +148,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
if (ret < 0)
goto err;
+ ret = batadv_gw_init(bat_priv);
+ if (ret < 0)
+ goto err;
+
atomic_set(&bat_priv->gw.reselect, 0);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
@@ -177,6 +182,8 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_dat_free(bat_priv);
+ batadv_gw_free(bat_priv);
+
free_percpu(bat_priv->bat_counters);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
@@ -118,6 +118,14 @@ enum batadv_bla_claimframe {
BATADV_CLAIM_TYPE_REQUEST = 0x03,
};
+/**
+ * enum batadv_tvlv_type - tvlv type definitions
+ * @BATADV_TVLV_GW: gateway tvlv
+ */
+enum batadv_tvlv_type {
+ BATADV_TVLV_GW = 0x01,
+};
+
/* the destination hardware field in the ARP frame is used to
* transport the claim type and the group id
*/
@@ -147,7 +155,7 @@ struct batadv_ogm_packet {
__be32 seqno;
uint8_t orig[ETH_ALEN];
uint8_t prev_sender[ETH_ALEN];
- uint8_t gw_flags; /* flags related to gateway class */
+ uint8_t reserved;
uint8_t tq;
uint8_t tt_num_changes;
uint8_t ttvn; /* translation table version number */
@@ -386,6 +386,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
batadv_gw_deselect(bat_priv);
atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
+ batadv_gw_tvlv_container_update(bat_priv);
return count;
}