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(v: &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, type: BATADV_TVLV_GW, version: 1); |
37 | break; |
38 | case BATADV_GW_MODE_SERVER: |
39 | down = atomic_read(v: &bat_priv->gw.bandwidth_down); |
40 | up = atomic_read(v: &bat_priv->gw.bandwidth_up); |
41 | gw.bandwidth_down = htonl(down); |
42 | gw.bandwidth_up = htonl(up); |
43 | batadv_tvlv_container_register(bat_priv, type: BATADV_TVLV_GW, version: 1, |
44 | tvlv_value: &gw, tvlv_value_len: 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_node: orig, gateway: &gateway); |
83 | |
84 | /* restart gateway selection */ |
85 | if (gateway.bandwidth_down != 0 && |
86 | atomic_read(v: &bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) |
87 | batadv_gw_check_election(bat_priv, orig_node: 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(v: &bat_priv->gw.sel_class, i: 1); |
100 | |
101 | batadv_tvlv_handler_register(bat_priv, optr: batadv_gw_tvlv_ogm_handler_v1, |
102 | NULL, NULL, type: BATADV_TVLV_GW, version: 1, |
103 | flags: 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, type: BATADV_TVLV_GW, version: 1); |
113 | batadv_tvlv_handler_unregister(bat_priv, type: BATADV_TVLV_GW, version: 1); |
114 | } |
115 | |