blob: 204d1deebf704e8665bd3ad790cdcfd487de649c [file] [log] [blame]
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +02001/* (C) 2015 by sysmocom s.f.m.c. GmbH
2 * All Rights Reserved
3 *
4 * Author: Neels Hofmeyr
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <string.h>
22
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +010023#include <ares.h>
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020028#include <osmocom/core/talloc.h>
29#include <osmocom/vty/command.h>
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +010030#include <osmocom/vty/misc.h>
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020031
32#include <openbsc/vty.h>
33#include <openbsc/gtphub.h>
34
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +010035/* TODO split GRX ares from sgsn into a separate struct and allow use without
36 * globals. */
37#include <openbsc/sgsn.h>
38extern struct sgsn_instance *sgsn;
39
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +010040static struct gtphub *g_hub = 0;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020041static struct gtphub_cfg *g_cfg = 0;
42
43static struct cmd_node gtphub_node = {
44 GTPHUB_NODE,
45 "%s(config-gtphub)# ",
46 1,
47};
48
49#define GTPH_DEFAULT_CONTROL_PORT 2123
50#define GTPH_DEFAULT_USER_PORT 2152
51
52static void write_addrs(struct vty *vty, const char *name,
53 struct gtphub_cfg_addr *c, struct gtphub_cfg_addr *u)
54{
55 if ((c->port == GTPH_DEFAULT_CONTROL_PORT)
56 && (u->port == GTPH_DEFAULT_USER_PORT)
57 && (strcmp(c->addr_str, u->addr_str) == 0)) {
58 /* Default port numbers and same IP address: write "short"
59 * variant. */
60 vty_out(vty, " %s %s%s",
61 name,
62 c->addr_str,
63 VTY_NEWLINE);
64 return;
65 }
66
67 vty_out(vty, " %s ctrl %s %d user %s %d%s",
68 name,
69 c->addr_str, (int)c->port,
70 u->addr_str, (int)u->port,
71 VTY_NEWLINE);
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +010072
73 struct ares_addr_node *server;
74 for (server = sgsn->ares_servers; server; server = server->next)
75 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020076}
77
78static int config_write_gtphub(struct vty *vty)
79{
80 vty_out(vty, "gtphub%s", VTY_NEWLINE);
81
82 write_addrs(vty, "bind-to-sgsns",
Neels Hofmeyra9905a52015-11-29 23:49:48 +010083 &g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].bind,
84 &g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER].bind);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020085
86 write_addrs(vty, "bind-to-ggsns",
Neels Hofmeyra9905a52015-11-29 23:49:48 +010087 &g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].bind,
88 &g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].bind);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020089
Neels Hofmeyr817bc322015-11-29 23:50:45 +010090 if (g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].addr_str) {
91 write_addrs(vty, "sgsn-proxy",
92 &g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL],
93 &g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER]);
94 }
95
Neels Hofmeyra9905a52015-11-29 23:49:48 +010096 if (g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str) {
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020097 write_addrs(vty, "ggsn-proxy",
Neels Hofmeyra9905a52015-11-29 23:49:48 +010098 &g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL],
99 &g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER]);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200100 }
101
102 return CMD_SUCCESS;
103}
104
105DEFUN(cfg_gtphub, cfg_gtphub_cmd,
106 "gtphub",
107 "Configure the GTP hub")
108{
109 vty->node = GTPHUB_NODE;
110 return CMD_SUCCESS;
111}
112
113#define BIND_ARGS "ctrl ADDR <0-65535> user ADDR <0-65535>"
114#define BIND_DOCS \
115 "Set GTP-C bind\n" \
116 "GTP-C local IP address (v4 or v6)\n" \
117 "GTP-C local port\n" \
118 "Set GTP-U bind\n" \
119 "GTP-U local IP address (v4 or v6)\n" \
120 "GTP-U local port\n"
121
122
123DEFUN(cfg_gtphub_bind_to_sgsns_short, cfg_gtphub_bind_to_sgsns_short_cmd,
124 "bind-to-sgsns ADDR",
125 "GTP Hub Parameters\n"
126 "Set the local bind address to listen for SGSNs, for both GTP-C and GTP-U\n"
127 "Local IP address (v4 or v6)\n"
128 )
129{
130 int i;
Neels Hofmeyrf9773202015-11-27 00:05:56 +0100131 for_each_plane(i)
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100132 g_cfg->to_gsns[GTPH_SIDE_SGSN][i].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
133 g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].bind.port = GTPH_DEFAULT_CONTROL_PORT;
134 g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER].bind.port = GTPH_DEFAULT_USER_PORT;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200135 return CMD_SUCCESS;
136}
137
138DEFUN(cfg_gtphub_bind_to_ggsns_short, cfg_gtphub_bind_to_ggsns_short_cmd,
139 "bind-to-ggsns ADDR",
140 "GTP Hub Parameters\n"
141 "Set the local bind address to listen for GGSNs, for both GTP-C and GTP-U\n"
142 "Local IP address (v4 or v6)\n"
143 )
144{
145 int i;
Neels Hofmeyrf9773202015-11-27 00:05:56 +0100146 for_each_plane(i)
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100147 g_cfg->to_gsns[GTPH_SIDE_GGSN][i].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
148 g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].bind.port = GTPH_DEFAULT_CONTROL_PORT;
149 g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].bind.port = GTPH_DEFAULT_USER_PORT;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200150 return CMD_SUCCESS;
151}
152
153
154static int handle_binds(struct gtphub_cfg_bind *b, const char **argv)
155{
156 b[GTPH_PLANE_CTRL].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
157 b[GTPH_PLANE_CTRL].bind.port = atoi(argv[1]);
158 b[GTPH_PLANE_USER].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
159 b[GTPH_PLANE_USER].bind.port = atoi(argv[3]);
160 return CMD_SUCCESS;
161}
162
163DEFUN(cfg_gtphub_bind_to_sgsns, cfg_gtphub_bind_to_sgsns_cmd,
164 "bind-to-sgsns " BIND_ARGS,
165 "GTP Hub Parameters\n"
166 "Set the local bind addresses and ports to listen for SGSNs\n"
167 BIND_DOCS
168 )
169{
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100170 return handle_binds(g_cfg->to_gsns[GTPH_SIDE_SGSN], argv);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200171}
172
173DEFUN(cfg_gtphub_bind_to_ggsns, cfg_gtphub_bind_to_ggsns_cmd,
174 "bind-to-ggsns " BIND_ARGS,
175 "GTP Hub Parameters\n"
176 "Set the local bind addresses and ports to listen for GGSNs\n"
177 BIND_DOCS
178 )
179{
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100180 return handle_binds(g_cfg->to_gsns[GTPH_SIDE_GGSN], argv);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200181}
182
183DEFUN(cfg_gtphub_ggsn_proxy_short, cfg_gtphub_ggsn_proxy_short_cmd,
184 "ggsn-proxy ADDR",
185 "GTP Hub Parameters\n"
186 "Redirect all GGSN bound traffic to default ports on this address (another gtphub)\n"
187 "Remote IP address (v4 or v6)\n"
188 )
189{
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100190 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
191 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].port = GTPH_DEFAULT_CONTROL_PORT;
192 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
193 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].port = GTPH_DEFAULT_USER_PORT;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200194 return CMD_SUCCESS;
195}
196
197DEFUN(cfg_gtphub_ggsn_proxy, cfg_gtphub_ggsn_proxy_cmd,
198 "ggsn-proxy " BIND_ARGS,
199 "GTP Hub Parameters\n"
200 "Redirect all GGSN bound traffic to these addresses and ports (another gtphub)\n"
201 BIND_DOCS
202 )
203{
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100204 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
205 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].port = atoi(argv[1]);
206 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
207 g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].port = atoi(argv[3]);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200208 return CMD_SUCCESS;
209}
210
211DEFUN(cfg_gtphub_sgsn_proxy_short, cfg_gtphub_sgsn_proxy_short_cmd,
212 "sgsn-proxy ADDR",
213 "GTP Hub Parameters\n"
214 "Redirect all SGSN bound traffic to default ports on this address (another gtphub)\n"
215 "Remote IP address (v4 or v6)\n"
216 )
217{
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100218 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
219 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].port = GTPH_DEFAULT_CONTROL_PORT;
220 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
221 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].port = GTPH_DEFAULT_USER_PORT;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200222 return CMD_SUCCESS;
223}
224
225DEFUN(cfg_gtphub_sgsn_proxy, cfg_gtphub_sgsn_proxy_cmd,
226 "sgsn-proxy " BIND_ARGS,
227 "GTP Hub Parameters\n"
228 "Redirect all SGSN bound traffic to these addresses and ports (another gtphub)\n"
229 BIND_DOCS
230 )
231{
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100232 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
233 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].port = atoi(argv[1]);
234 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
235 g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].port = atoi(argv[3]);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200236 return CMD_SUCCESS;
237}
238
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +0100239
240/* Copied from sgsn_vty.h */
241DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
242 "grx-dns-add A.B.C.D",
243 "Add DNS server\nIPv4 address\n")
244{
245 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
246 node->family = AF_INET;
247 inet_aton(argv[0], &node->addr.addr4);
248
249 node->next = sgsn->ares_servers;
250 sgsn->ares_servers = node;
251 return CMD_SUCCESS;
252}
253
254
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100255/*
256(show gtphub all, show gtphub stats, show gtphub teidmap,
257 show gtphub peers, ...)
258*/
259
260static void show_bind_stats_all(struct vty *vty)
261{
262 int plane_idx;
Neels Hofmeyrf9773202015-11-27 00:05:56 +0100263 for_each_plane(plane_idx) {
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100264 vty_out(vty, "- %s Plane:%s",
265 gtphub_plane_idx_names[plane_idx], VTY_NEWLINE);
266
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100267 struct gtphub_bind *b = &g_hub->to_gsns[GTPH_SIDE_GGSN][plane_idx];
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100268 vty_out(vty, " - to/from GGSNs: %s port %d%s",
269 gsn_addr_to_str(&b->local_addr), (int)b->local_port,
270 VTY_NEWLINE);
271 vty_out_rate_ctr_group(vty, " ", b->counters_io);
272
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100273 b = &g_hub->to_gsns[GTPH_SIDE_SGSN][plane_idx];
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100274 vty_out(vty, " - to/from SGSNs: %s port %d%s",
275 gsn_addr_to_str(&b->local_addr), (int)b->local_port,
276 VTY_NEWLINE);
277 vty_out_rate_ctr_group(vty, " ", b->counters_io);
278 }
279}
280
281/*
282static void show_peers_summary(struct vty *vty)
283{
284 int c
285 int plane_idx;
286}
287*/
288
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100289static void show_tunnels_summary(struct vty *vty)
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100290{
291 time_t now = gtphub_now();
292
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100293 const int w = 36;
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100294 int max_expiry = g_hub->expire_slowly.expiry_in_seconds;
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100295 float seconds_per_step = ((float)max_expiry) / w;
296
297 /* Print TEI mapping expiry in an ASCII histogram, like:
298 TEI map summary
299 Legend: '_'=0 '.'<=1% ':'<=2% '|'<=10% '#'>10% (10.0 m/step)
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100300 CTRL: 30 mappings, valid for 360m[# :. | . : . ]1m
301 USER: 30 mappings, valid for 360m[# :. | . : . ]1m
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100302 4 TEI mappings in total, last expiry in 359.4 min
303 */
304 vty_out(vty,
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100305 "Tunnels summary%s"
306 " Legend: ' '=0 '.'<=1%% ':'<=2%% '|'<=10%% '#'>10%% (%.1f m/step)%s",
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100307 VTY_NEWLINE,
308 seconds_per_step / 60.,
309 VTY_NEWLINE);
310
311 int last_expiry = 0;
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100312
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100313 unsigned int count = 0;
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100314
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100315 int histogram[w];
316 memset(histogram, 0, sizeof(histogram));
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100317
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100318 struct gtphub_tunnel *t;
319 llist_for_each_entry(t, &g_hub->tunnels, entry) {
320 count ++;
321 int expiry = t->expiry_entry.expiry - now;
322 last_expiry = (last_expiry > expiry) ? last_expiry : expiry;
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100323
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100324 int hi = ((float)expiry) / seconds_per_step;
325 if (hi < 0)
326 hi = 0;
327 if (hi > (w - 1))
328 hi = w - 1;
329 histogram[hi] ++;
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100330 }
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100331
332 vty_out(vty,
333 " %u tunnels, valid for %dm[",
334 count, max_expiry / 60);
335
336 int i;
337 for (i = w - 1; i >= 0; i--) {
338 char c;
339 int val = histogram[i];
340 int percent = 100. * val / count;
341 if (!val)
342 c = ' ';
343 else if (percent <= 1)
344 c = '.';
345 else if (percent <= 2)
346 c = ':';
347 else if (percent <= 10)
348 c = '|';
349 else c = '#';
350 vty_out(vty, "%c", c);
351 }
352 vty_out(vty, "]1m%s", VTY_NEWLINE);
353
354 vty_out(vty, " last expiry in %.1f min%s",
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100355 ((float)last_expiry) / 60.,
356 VTY_NEWLINE);
357}
358
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100359static void show_tunnels_all(struct vty *vty)
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100360{
361 time_t now = gtphub_now();
362
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100363 vty_out(vty, "All tunnels:%s"
364 "Legend: SGSN <-> GGSN, with each:%s"
365 " <IP-Ctrl>[/<IP-User>] (<TEI-Ctrl>=<mapped>/<TEI-User>=<mapped>)%s",
366 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100367
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100368 unsigned int count = 0;
369 unsigned int incomplete = 0;
370 struct gtphub_tunnel *t;
371 llist_for_each_entry(t, &g_hub->tunnels, entry) {
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100372 vty_out(vty,
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100373 "(%4dm) %s%s",
374 -(int)((t->expiry_entry.expiry - now) / 60),
375 gtphub_tunnel_str(t),
376 VTY_NEWLINE);
377 count ++;
378 if (!gtphub_tunnel_complete(t))
379 incomplete ++;
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100380 }
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100381 vty_out(vty, "Total: %u tunnels%s", count, VTY_NEWLINE);
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100382}
383
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100384DEFUN(show_gtphub_tunnels_summary, show_gtphub_tunnels_summary_cmd, "show gtphub tunnels summary",
385 SHOW_STR "Summary of all tunnels")
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100386{
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100387 show_tunnels_summary(vty);
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100388 return CMD_SUCCESS;
389}
390
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100391DEFUN(show_gtphub_tunnels_list, show_gtphub_tunnels_list_cmd, "show gtphub tunnels list",
392 SHOW_STR "List all tunnels")
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100393{
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100394 show_tunnels_all(vty);
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100395 return CMD_SUCCESS;
396}
397
398DEFUN(show_gtphub, show_gtphub_cmd, "show gtphub all",
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200399 SHOW_STR "Display information about the GTP hub")
400{
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100401 show_bind_stats_all(vty);
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100402 show_tunnels_summary(vty);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200403 return CMD_SUCCESS;
404}
405
406
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100407int gtphub_vty_init(struct gtphub *global_hub, struct gtphub_cfg *global_cfg)
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200408{
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100409 g_hub = global_hub;
410 g_cfg = global_cfg;
411
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200412 install_element_ve(&show_gtphub_cmd);
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100413 install_element_ve(&show_gtphub_tunnels_summary_cmd);
414 install_element_ve(&show_gtphub_tunnels_list_cmd);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200415
416 install_element(CONFIG_NODE, &cfg_gtphub_cmd);
417 install_node(&gtphub_node, config_write_gtphub);
418 vty_install_default(GTPHUB_NODE);
419
420 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_sgsns_short_cmd);
421 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_sgsns_cmd);
422 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_ggsns_short_cmd);
423 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_ggsns_cmd);
424 install_element(GTPHUB_NODE, &cfg_gtphub_ggsn_proxy_short_cmd);
425 install_element(GTPHUB_NODE, &cfg_gtphub_ggsn_proxy_cmd);
426 install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_short_cmd);
427 install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_cmd);
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +0100428 install_element(GTPHUB_NODE, &cfg_grx_ggsn_cmd);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200429
430 return 0;
431}
432
433int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file)
434{
435 int rc;
436
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200437 rc = vty_read_config_file(config_file, NULL);
438 if (rc < 0) {
439 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
440 return rc;
441 }
442
443 return 0;
444}