162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (C) B.A.T.M.A.N. contributors: 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Marek Lindner 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "gateway_common.h" 862306a36Sopenharmony_ci#include "main.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/atomic.h> 1162306a36Sopenharmony_ci#include <linux/byteorder/generic.h> 1262306a36Sopenharmony_ci#include <linux/stddef.h> 1362306a36Sopenharmony_ci#include <linux/types.h> 1462306a36Sopenharmony_ci#include <uapi/linux/batadv_packet.h> 1562306a36Sopenharmony_ci#include <uapi/linux/batman_adv.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "gateway_client.h" 1862306a36Sopenharmony_ci#include "tvlv.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/** 2162306a36Sopenharmony_ci * batadv_gw_tvlv_container_update() - update the gw tvlv container after 2262306a36Sopenharmony_ci * gateway setting change 2362306a36Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_civoid batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct batadv_tvlv_gateway_data gw; 2862306a36Sopenharmony_ci u32 down, up; 2962306a36Sopenharmony_ci char gw_mode; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci gw_mode = atomic_read(&bat_priv->gw.mode); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci switch (gw_mode) { 3462306a36Sopenharmony_ci case BATADV_GW_MODE_OFF: 3562306a36Sopenharmony_ci case BATADV_GW_MODE_CLIENT: 3662306a36Sopenharmony_ci batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 3762306a36Sopenharmony_ci break; 3862306a36Sopenharmony_ci case BATADV_GW_MODE_SERVER: 3962306a36Sopenharmony_ci down = atomic_read(&bat_priv->gw.bandwidth_down); 4062306a36Sopenharmony_ci up = atomic_read(&bat_priv->gw.bandwidth_up); 4162306a36Sopenharmony_ci gw.bandwidth_down = htonl(down); 4262306a36Sopenharmony_ci gw.bandwidth_up = htonl(up); 4362306a36Sopenharmony_ci batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, 4462306a36Sopenharmony_ci &gw, sizeof(gw)); 4562306a36Sopenharmony_ci break; 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/** 5062306a36Sopenharmony_ci * batadv_gw_tvlv_ogm_handler_v1() - process incoming gateway tvlv container 5162306a36Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information 5262306a36Sopenharmony_ci * @orig: the orig_node of the ogm 5362306a36Sopenharmony_ci * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 5462306a36Sopenharmony_ci * @tvlv_value: tvlv buffer containing the gateway data 5562306a36Sopenharmony_ci * @tvlv_value_len: tvlv buffer length 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_cistatic void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 5862306a36Sopenharmony_ci struct batadv_orig_node *orig, 5962306a36Sopenharmony_ci u8 flags, 6062306a36Sopenharmony_ci void *tvlv_value, u16 tvlv_value_len) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct batadv_tvlv_gateway_data gateway, *gateway_ptr; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* only fetch the tvlv value if the handler wasn't called via the 6562306a36Sopenharmony_ci * CIFNOTFND flag and if there is data to fetch 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_ci if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND || 6862306a36Sopenharmony_ci tvlv_value_len < sizeof(gateway)) { 6962306a36Sopenharmony_ci gateway.bandwidth_down = 0; 7062306a36Sopenharmony_ci gateway.bandwidth_up = 0; 7162306a36Sopenharmony_ci } else { 7262306a36Sopenharmony_ci gateway_ptr = tvlv_value; 7362306a36Sopenharmony_ci gateway.bandwidth_down = gateway_ptr->bandwidth_down; 7462306a36Sopenharmony_ci gateway.bandwidth_up = gateway_ptr->bandwidth_up; 7562306a36Sopenharmony_ci if (gateway.bandwidth_down == 0 || 7662306a36Sopenharmony_ci gateway.bandwidth_up == 0) { 7762306a36Sopenharmony_ci gateway.bandwidth_down = 0; 7862306a36Sopenharmony_ci gateway.bandwidth_up = 0; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci batadv_gw_node_update(bat_priv, orig, &gateway); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* restart gateway selection */ 8562306a36Sopenharmony_ci if (gateway.bandwidth_down != 0 && 8662306a36Sopenharmony_ci atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) 8762306a36Sopenharmony_ci batadv_gw_check_election(bat_priv, orig); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/** 9162306a36Sopenharmony_ci * batadv_gw_init() - initialise the gateway handling internals 9262306a36Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_civoid batadv_gw_init(struct batadv_priv *bat_priv) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci if (bat_priv->algo_ops->gw.init_sel_class) 9762306a36Sopenharmony_ci bat_priv->algo_ops->gw.init_sel_class(bat_priv); 9862306a36Sopenharmony_ci else 9962306a36Sopenharmony_ci atomic_set(&bat_priv->gw.sel_class, 1); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, 10262306a36Sopenharmony_ci NULL, NULL, BATADV_TVLV_GW, 1, 10362306a36Sopenharmony_ci BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/** 10762306a36Sopenharmony_ci * batadv_gw_free() - free the gateway handling internals 10862306a36Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_civoid batadv_gw_free(struct batadv_priv *bat_priv) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 11362306a36Sopenharmony_ci batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); 11462306a36Sopenharmony_ci} 115