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/byteorder/generic.h> 11 #include <linux/compiler.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 mesh interface information 24 */ 25 void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) 26 { 27 struct batadv_tvlv_gateway_data gw; 28 enum batadv_gw_modes gw_mode; 29 u32 down; 30 u32 up; 31 32 gw_mode = READ_ONCE(bat_priv->gw.mode); 33 34 switch (gw_mode) { 35 case BATADV_GW_MODE_OFF: 36 case BATADV_GW_MODE_CLIENT: 37 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 38 break; 39 case BATADV_GW_MODE_SERVER: 40 down = READ_ONCE(bat_priv->gw.bandwidth_down); 41 up = READ_ONCE(bat_priv->gw.bandwidth_up); 42 gw.bandwidth_down = htonl(down); 43 gw.bandwidth_up = htonl(up); 44 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, 45 &gw, sizeof(gw)); 46 break; 47 } 48 } 49 50 /** 51 * batadv_gw_tvlv_ogm_handler_v1() - process incoming gateway tvlv container 52 * @bat_priv: the bat priv with all the mesh interface information 53 * @orig: the orig_node of the ogm 54 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 55 * @tvlv_value: tvlv buffer containing the gateway data 56 * @tvlv_value_len: tvlv buffer length 57 */ 58 static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 59 struct batadv_orig_node *orig, 60 u8 flags, 61 void *tvlv_value, u16 tvlv_value_len) 62 { 63 struct batadv_tvlv_gateway_data *gateway_ptr; 64 struct batadv_tvlv_gateway_data gateway; 65 66 /* only fetch the tvlv value if the handler wasn't called via the 67 * CIFNOTFND flag and if there is data to fetch 68 */ 69 if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND || 70 tvlv_value_len < sizeof(gateway)) { 71 gateway.bandwidth_down = 0; 72 gateway.bandwidth_up = 0; 73 } else { 74 gateway_ptr = tvlv_value; 75 gateway.bandwidth_down = gateway_ptr->bandwidth_down; 76 gateway.bandwidth_up = gateway_ptr->bandwidth_up; 77 if (gateway.bandwidth_down == 0 || 78 gateway.bandwidth_up == 0) { 79 gateway.bandwidth_down = 0; 80 gateway.bandwidth_up = 0; 81 } 82 } 83 84 batadv_gw_node_update(bat_priv, orig, &gateway); 85 86 /* restart gateway selection */ 87 if (gateway.bandwidth_down != 0 && 88 READ_ONCE(bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) 89 batadv_gw_check_election(bat_priv, orig); 90 } 91 92 /** 93 * batadv_gw_init() - initialise the gateway handling internals 94 * @bat_priv: the bat priv with all the mesh interface information 95 */ 96 void batadv_gw_init(struct batadv_priv *bat_priv) 97 { 98 if (bat_priv->algo_ops->gw.init_sel_class) 99 bat_priv->algo_ops->gw.init_sel_class(bat_priv); 100 else 101 WRITE_ONCE(bat_priv->gw.sel_class, 1); 102 103 batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, 104 NULL, NULL, BATADV_TVLV_GW, 1, 105 BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 106 } 107 108 /** 109 * batadv_gw_free() - free the gateway handling internals 110 * @bat_priv: the bat priv with all the mesh interface information 111 */ 112 void batadv_gw_free(struct batadv_priv *bat_priv) 113 { 114 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 115 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); 116 } 117