neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-upf/+/37830?usp=email )
Change subject: add VTY 'gtp-echo' command ......................................................................
add VTY 'gtp-echo' command
Allow sending GTPv1-U Echo Requests to GTP peers via new VTY command
gtp-echo tx to 1.2.3.4 [from (dev|ip) (apn0|5.6.7.8)]
(pseudocode)
Related: OS#6541 Change-Id: I970dccd7a27b098eea9e660822e24e2c4b059fc6 --- M include/osmocom/upf/upf.h M include/osmocom/upf/upf_gtpu_echo.h M src/osmo-upf/upf_gtpu_echo.c M src/osmo-upf/upf_vty.c A tests/gtp-echo.vty 5 files changed, 295 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-upf refs/changes/30/37830/1
diff --git a/include/osmocom/upf/upf.h b/include/osmocom/upf/upf.h index db73c1f..abd881e 100644 --- a/include/osmocom/upf/upf.h +++ b/include/osmocom/upf/upf.h @@ -117,6 +117,7 @@
struct { uint32_t next_local_teid_state; + uint16_t next_echo_seq_nr; } gtp;
struct llist_head netinst; diff --git a/include/osmocom/upf/upf_gtpu_echo.h b/include/osmocom/upf/upf_gtpu_echo.h index 2575424..2bb7c31 100644 --- a/include/osmocom/upf/upf_gtpu_echo.h +++ b/include/osmocom/upf/upf_gtpu_echo.h @@ -2,3 +2,4 @@ #pragma once
int upf_gtpu_echo_setup(struct upf_gtp_dev *dev); +int upf_gtpu_echo_req_tx(struct upf_gtp_dev *dev, const struct osmo_sockaddr *remote, uint16_t seq_nr); diff --git a/src/osmo-upf/upf_gtpu_echo.c b/src/osmo-upf/upf_gtpu_echo.c index b234065..8d8db0c 100644 --- a/src/osmo-upf/upf_gtpu_echo.c +++ b/src/osmo-upf/upf_gtpu_echo.c @@ -122,6 +122,45 @@ return rc; }
+int upf_gtpu_echo_req_tx(struct upf_gtp_dev *dev, const struct osmo_sockaddr *remote, uint16_t seq_nr) +{ + struct gtp1u_hdr *tx_h; + int rc; + +#define GTP_ECHO_REQ_SIZE ((size_t)(sizeof(struct gtp1u_hdr) + 2)) + uint8_t msgbuf[GTP_ECHO_REQ_SIZE]; + + tx_h = (void *)msgbuf; + *tx_h = (struct gtp1u_hdr){ + /* 3GPP TS 29.281 5.1 defines that the ECHO REQ & RESP shall contain a sequence nr */ + .s = 1, + .pt = 1, + .version = 1, + .msg_type = GTP1U_MSGTYPE_ECHO_REQ, + .ext = { + .seq_nr = seq_nr, + }, + }; + + /* ECHO REQUEST shall contain a recovery counter */ + tx_h->data2[0] = GTP1U_IEI_RECOVERY; + tx_h->data2[1] = g_upf->tunend.recovery_count; + + osmo_store16be(GTP_ECHO_REQ_SIZE - offsetof(struct gtp1u_hdr, data1), &tx_h->length); + + rc = sendto(dev->gtpv1.ofd.fd, msgbuf, GTP_ECHO_REQ_SIZE, 0, &remote->u.sa, sizeof(*remote)); + if (rc < 0) { + rc = -errno; + LOG_GTP_DEV(dev, LOGL_ERROR, "GTP1-U sendto(len=%zu, to=%s): %s\n", GTP_ECHO_REQ_SIZE, + osmo_sockaddr_to_str(remote), strerror(-rc)); + } else { + rc = 0; + } + LOG_GTP_DEV(dev, LOGL_INFO, "<- %s: tx GTP1-U Echo Request: seq_nr=%u recovery_count=%u\n", + osmo_sockaddr_to_str(remote), seq_nr, g_upf->tunend.recovery_count); + return rc; +} + int upf_gtpu_echo_read_cb(struct osmo_fd *ofd, unsigned int what) { struct upf_gtp_dev *dev = ofd->data; diff --git a/src/osmo-upf/upf_vty.c b/src/osmo-upf/upf_vty.c index 44d14db..76d18ea 100644 --- a/src/osmo-upf/upf_vty.c +++ b/src/osmo-upf/upf_vty.c @@ -38,6 +38,7 @@ #include <osmocom/upf/up_session.h> #include <osmocom/upf/up_gtp_action.h> #include <osmocom/upf/netinst.h> +#include <osmocom/upf/upf_gtpu_echo.h>
enum upf_vty_node { PFCP_NODE = _LAST_OSMOVTY_NODE + 1, @@ -486,6 +487,80 @@ return CMD_SUCCESS; }
+DEFUN(gtp_echo_tx, gtp_echo_tx_cmd, + "gtp-echo tx to IP_ADDR [from] [(ip|dev)] [LOCAL_ADDR_OR_DEV_NAME]", + "GTP1-U Echo probing\n" + "Send a GTP1-U Echo Request to a remote peer\n" + "Send to remote peer's GTP address\n" "IP address like 1.2.3.4 or 1:2:3::4\n" + "Choose local GTP device to send from; when omitted, choose first GTP device.\n" + "Choose local GTP device by IP address\n" + "Choose local GTP device by configured name\n" + "A local IP address bound by a GTP device | a GTP device name as in cfg\n") +{ + struct osmo_sockaddr_str addr; + struct osmo_sockaddr osa_remote; + struct osmo_sockaddr osa_local; + struct upf_gtp_dev *gtp_dev = NULL; + const char *remote_str = argv[0]; + const char *local_type = NULL; + const char *local_str = NULL; + if (argc > 1 && argc <= 3) { + vty_out(vty, "%% Error: missing argument after '%s'%s", argv[argc - 1], VTY_NEWLINE); + return CMD_WARNING; + } + if (argc > 2) + local_type = argv[2]; + if (argc > 3) + local_str = argv[3]; + + /* GTP can be received on port 2152 only, i.e. the remote port must be 2152. (The sending port is allowed to + * differ). */ + if (osmo_sockaddr_str_from_str(&addr, remote_str, 2152) + || osmo_sockaddr_str_to_osa(&addr, &osa_remote)) { + vty_out(vty, "%% Error: invalid IP address: %s%s", osmo_quote_str(remote_str, -1), VTY_NEWLINE); + return CMD_WARNING; + } + + if (local_type) { + if (!strcmp(local_type, "ip")) { + if (osmo_sockaddr_str_from_str(&addr, local_str, 2152) + || osmo_sockaddr_str_to_osa(&addr, &osa_local)) { + vty_out(vty, "%% Error: invalid IP address: %s%s", osmo_quote_str(local_str, -1), VTY_NEWLINE); + return CMD_WARNING; + } + gtp_dev = upf_gtp_dev_find_by_local_addr(&osa_local); + if (!gtp_dev) { + vty_out(vty, "%% Error: this does not seem to be a locally bound GTP address: %s%s", + osmo_sockaddr_to_str_c(OTC_SELECT, &osa_local), VTY_NEWLINE); + return CMD_WARNING; + } + } else { + gtp_dev = upf_gtp_dev_find_by_name(local_str); + if (!gtp_dev) { + vty_out(vty, "%% Error: there is no GTP device by the name of '%s'%s", + local_str, VTY_NEWLINE); + return CMD_WARNING; + } + } + } else { + gtp_dev = llist_first_entry_or_null(&g_upf->tunend.devs, struct upf_gtp_dev, entry); + if (!gtp_dev) { + vty_out(vty, "%% Error: there is no GTP device to send Echo from%s", + VTY_NEWLINE); + return CMD_WARNING; + } + } + OSMO_ASSERT(gtp_dev); + + if (upf_gtpu_echo_req_tx(gtp_dev, &osa_remote, g_upf->gtp.next_echo_seq_nr++)) { + vty_out(vty, "%%Error: Failed to transmit Echo Request (see DGTP logging)%s", VTY_NEWLINE); + return CMD_WARNING; + } + vty_out(vty, "%s -> %s tx Echo Request; for responses, see DGTP logging level INFO%s", + gtp_dev->name, osmo_sockaddr_to_str_c(OTC_SELECT, &osa_remote), VTY_NEWLINE); + return CMD_SUCCESS; +} + void upf_vty_init() { OSMO_ASSERT(g_upf != NULL); @@ -495,6 +570,7 @@ install_element_ve(&show_session_cmd); install_element_ve(&show_netinst_cmd); install_element_ve(&show_nft_rule_append_cmd); + install_element_ve(>p_echo_tx_cmd);
install_node(&cfg_pfcp_node, config_write_pfcp); install_element(CONFIG_NODE, &cfg_pfcp_cmd); diff --git a/tests/gtp-echo.vty b/tests/gtp-echo.vty new file mode 100644 index 0000000..620d36c --- /dev/null +++ b/tests/gtp-echo.vty @@ -0,0 +1,178 @@ +OsmoUPF> list + show pid + show uptime + show version + show online-help + list [with-flags] + exit + help + show vty-attributes + show vty-attributes (application|library|global) + enable [expert-mode] + terminal length <0-512> + terminal no length + who + show history + logging enable + logging disable + logging filter all (0|1) + logging color (0|1) + logging timestamp (0|1) + logging print extended-timestamp (0|1) + logging print thread-id (0|1) + logging print category (0|1) + logging print category-hex (0|1) + logging print level (0|1) + logging print file (0|1|basename) [last] + logging set-log-mask MASK + logging level (ref|peer|session|gtp|nft|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro|lns|lbssgp|lnsdata|lnssignal|liuup|lpfcp|lcsn1|lio) (debug|info|notice|error|fatal) + logging level set-all (debug|info|notice|error|fatal) + logging level force-all (debug|info|notice|error|fatal) + no logging level force-all + logp (ref|peer|session|gtp|nft|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro|lns|lbssgp|lnsdata|lnssignal|liuup|lpfcp|lcsn1|lio) (debug|info|notice|error|fatal) .LOGMESSAGE + show logging vty + show alarms + show talloc-context (application|global|all) (full|brief|DEPTH) + show talloc-context (application|global|all) (full|brief|DEPTH) tree ADDRESS + show talloc-context (application|global|all) (full|brief|DEPTH) filter REGEXP + show cpu-sched threads + show pdr + show gtp + show session + show netinst [NAME] + gtp-echo tx to IP_ADDR [from] [(ip|dev)] [LOCAL_ADDR_OR_DEV_NAME] + show timer [(pfcp)] [TNNNN] +OsmoUPF> enable +OsmoUPF# list + help + list [with-flags] + show vty-attributes + show vty-attributes (application|library|global) + write terminal + write file [PATH] + write memory + write + show running-config + exit + disable + configure [terminal] + copy running-config startup-config + shutdown + show startup-config + show version + show online-help + terminal length <0-512> + terminal no length + who + show history + terminal monitor + terminal no monitor + logging enable + logging disable + logging filter all (0|1) + logging color (0|1) + logging timestamp (0|1) + logging print extended-timestamp (0|1) + logging print thread-id (0|1) + logging print category (0|1) + logging print category-hex (0|1) + logging print level (0|1) + logging print file (0|1|basename) [last] + logging set-log-mask MASK + logging level (ref|peer|session|gtp|nft|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro|lns|lbssgp|lnsdata|lnssignal|liuup|lpfcp|lcsn1|lio) (debug|info|notice|error|fatal) + logging level set-all (debug|info|notice|error|fatal) + logging level force-all (debug|info|notice|error|fatal) + no logging level force-all + logp (ref|peer|session|gtp|nft|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro|lns|lbssgp|lnsdata|lnssignal|liuup|lpfcp|lcsn1|lio) (debug|info|notice|error|fatal) .LOGMESSAGE + show logging vty + show alarms + show talloc-context (application|global|all) (full|brief|DEPTH) + show talloc-context (application|global|all) (full|brief|DEPTH) tree ADDRESS + show talloc-context (application|global|all) (full|brief|DEPTH) filter REGEXP + show cpu-sched threads + show pdr + show gtp + show session + show netinst [NAME] + gtp-echo tx to IP_ADDR [from] [(ip|dev)] [LOCAL_ADDR_OR_DEV_NAME] + show timer [(pfcp)] [TNNNN] +OsmoUPF# configure terminal +OsmoUPF(config)# list + help + list [with-flags] + show vty-attributes + show vty-attributes (application|library|global) + write terminal + write file [PATH] + write memory + write + show running-config + exit + end + hostname WORD + no hostname [HOSTNAME] + password (8|) WORD + password LINE + enable password (8|) WORD + enable password LINE + no enable password + banner motd default + banner motd file [FILE] + no banner motd + service terminal-length <0-512> + no service terminal-length [<0-512>] + line vty + service advanced-vty + no service advanced-vty + show history + ctrl + log stderr [blocking-io] + no log stderr + log file FILENAME [blocking-io] + no log file FILENAME + log alarms <2-32700> + no log alarms + log syslog (authpriv|cron|daemon|ftp|lpr|mail|news|user|uucp) + log syslog local <0-7> + no log syslog + log systemd-journal [raw] + no log systemd-journal + log gsmtap [HOSTNAME] + no log gsmtap [HOSTNAME] + cpu-sched + pfcp + tunend + tunmap + netinst + timer [(pfcp)] [TNNNN] [(<0-2147483647>|default)] +OsmoUPF(config)# end + +OsmoUPF# gtp-echo? + gtp-echo GTP1-U Echo probing +OsmoUPF# gtp-echo ? + tx Send a GTP1-U Echo Request to a remote peer +OsmoUPF# gtp-echo tx ? + to Send to remote peer's GTP address +OsmoUPF# gtp-echo tx to ? + IP_ADDR IP address like 1.2.3.4 or 1:2:3::4 +OsmoUPF# gtp-echo tx to 1.2.3.4 ? + [from] Choose local GTP device to send from; when omitted, choose first GTP device. +OsmoUPF# gtp-echo tx to 1.2.3.4 from ? + [ip] Choose local GTP device by IP address + [dev] Choose local GTP device by configured name +OsmoUPF# gtp-echo tx to 1.2.3.4 from ip ? + [LOCAL_ADDR_OR_DEV_NAME] A local IP address bound by a GTP device | a GTP device name as in cfg +OsmoUPF# gtp-echo tx to 1.2.3.4 from dev ? + [LOCAL_ADDR_OR_DEV_NAME] A local IP address bound by a GTP device | a GTP device name as in cfg +OsmoUPF# gtp-echo tx to 1.2.3.4 +% Error: there is no GTP device to send Echo from +OsmoUPF# gtp-echo tx to 1.2.3.4 from +% Error: missing argument after 'from' +OsmoUPF# gtp-echo tx to 1.2.3.4 from ip +% Error: missing argument after 'ip' +OsmoUPF# gtp-echo tx to 1.2.3.4 from dev +% Error: missing argument after 'dev' +OsmoUPF# gtp-echo tx to 1.2.3.4 from ip 1.2.3.4 +% Error: this does not seem to be a locally bound GTP address: 1.2.3.4:2152 +OsmoUPF# gtp-echo tx to 1.2.3.4 from dev apn0 +% Error: there is no GTP device by the name of 'apn0'