1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (C) B.A.T.M.A.N. contributors: 3 * 4 * Marek Lindner 5 */ 6 7#include "gateway_common.h" 8#include "main.h" 9 10#include <linux/atomic.h> 11#include <linux/byteorder/generic.h> 12#include <linux/stddef.h> 13#include <linux/types.h> 14#include <uapi/linux/batadv_packet.h> 15#include <uapi/linux/batman_adv.h> 16 17#include "gateway_client.h" 18#include "tvlv.h" 19 20/** 21 * batadv_gw_tvlv_container_update() - update the gw tvlv container after 22 * gateway setting change 23 * @bat_priv: the bat priv with all the soft interface information 24 */ 25void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) 26{ 27 struct batadv_tvlv_gateway_data gw; 28 u32 down, up; 29 char gw_mode; 30 31 gw_mode = atomic_read(&bat_priv->gw.mode); 32 33 switch (gw_mode) { 34 case BATADV_GW_MODE_OFF: 35 case BATADV_GW_MODE_CLIENT: 36 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 37 break; 38 case BATADV_GW_MODE_SERVER: 39 down = atomic_read(&bat_priv->gw.bandwidth_down); 40 up = atomic_read(&bat_priv->gw.bandwidth_up); 41 gw.bandwidth_down = htonl(down); 42 gw.bandwidth_up = htonl(up); 43 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, 44 &gw, sizeof(gw)); 45 break; 46 } 47} 48 49/** 50 * batadv_gw_tvlv_ogm_handler_v1() - process incoming gateway tvlv container 51 * @bat_priv: the bat priv with all the soft interface information 52 * @orig: the orig_node of the ogm 53 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 54 * @tvlv_value: tvlv buffer containing the gateway data 55 * @tvlv_value_len: tvlv buffer length 56 */ 57static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 58 struct batadv_orig_node *orig, 59 u8 flags, 60 void *tvlv_value, u16 tvlv_value_len) 61{ 62 struct batadv_tvlv_gateway_data gateway, *gateway_ptr; 63 64 /* only fetch the tvlv value if the handler wasn't called via the 65 * CIFNOTFND flag and if there is data to fetch 66 */ 67 if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND || 68 tvlv_value_len < sizeof(gateway)) { 69 gateway.bandwidth_down = 0; 70 gateway.bandwidth_up = 0; 71 } else { 72 gateway_ptr = tvlv_value; 73 gateway.bandwidth_down = gateway_ptr->bandwidth_down; 74 gateway.bandwidth_up = gateway_ptr->bandwidth_up; 75 if (gateway.bandwidth_down == 0 || 76 gateway.bandwidth_up == 0) { 77 gateway.bandwidth_down = 0; 78 gateway.bandwidth_up = 0; 79 } 80 } 81 82 batadv_gw_node_update(bat_priv, orig, &gateway); 83 84 /* restart gateway selection */ 85 if (gateway.bandwidth_down != 0 && 86 atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) 87 batadv_gw_check_election(bat_priv, orig); 88} 89 90/** 91 * batadv_gw_init() - initialise the gateway handling internals 92 * @bat_priv: the bat priv with all the soft interface information 93 */ 94void batadv_gw_init(struct batadv_priv *bat_priv) 95{ 96 if (bat_priv->algo_ops->gw.init_sel_class) 97 bat_priv->algo_ops->gw.init_sel_class(bat_priv); 98 else 99 atomic_set(&bat_priv->gw.sel_class, 1); 100 101 batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, 102 NULL, NULL, BATADV_TVLV_GW, 1, 103 BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 104} 105 106/** 107 * batadv_gw_free() - free the gateway handling internals 108 * @bat_priv: the bat priv with all the soft interface information 109 */ 110void batadv_gw_free(struct batadv_priv *bat_priv) 111{ 112 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 113 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); 114} 115