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 */ 25 void 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 */ 57 static 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 */ 94 void 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 */ 110 void 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