|
|
|
|
@@ -234,7 +234,7 @@ DEFUN(peer_retrans_req, peer_retrans_req_cmd,
|
|
|
|
|
else
|
|
|
|
|
*m = peer->last_resp;
|
|
|
|
|
|
|
|
|
|
OSMO_LOG_PFCP_MSG(m, LOGL_DEBUG, "retrans %s\n", argv[0]);
|
|
|
|
|
OSMO_LOG_PFCP_MSG(m, LOGL_INFO, "retrans %s\n", argv[0]);
|
|
|
|
|
|
|
|
|
|
rc = osmo_pfcp_endpoint_tx_data(g_pfcp_tool->ep, m);
|
|
|
|
|
if (rc) {
|
|
|
|
|
@@ -261,15 +261,15 @@ DEFUN(session, session_cmd,
|
|
|
|
|
{
|
|
|
|
|
struct pfcp_tool_peer *peer = vty->index;
|
|
|
|
|
struct pfcp_tool_session *session;
|
|
|
|
|
enum up_gtp_action_kind gtp_action = UP_GTP_U_TUNEND;
|
|
|
|
|
enum up_gtp_action_kind kind = UP_GTP_U_TUNEND;
|
|
|
|
|
|
|
|
|
|
if (argc > 0 && !strcmp(argv[0], "tunmap"))
|
|
|
|
|
gtp_action = UP_GTP_U_TUNMAP;
|
|
|
|
|
kind = UP_GTP_U_TUNMAP;
|
|
|
|
|
|
|
|
|
|
if (argc > 1)
|
|
|
|
|
session = pfcp_tool_session_find_or_create(peer, atoll(argv[1]), gtp_action);
|
|
|
|
|
session = pfcp_tool_session_find_or_create(peer, atoll(argv[1]), kind);
|
|
|
|
|
else
|
|
|
|
|
session = pfcp_tool_session_find_or_create(peer, peer_new_seid(peer), gtp_action);
|
|
|
|
|
session = pfcp_tool_session_find_or_create(peer, peer_new_seid(peer), kind);
|
|
|
|
|
|
|
|
|
|
vty->index = session;
|
|
|
|
|
vty->node = SESSION_NODE;
|
|
|
|
|
@@ -288,54 +288,112 @@ DEFUN(s_ue, s_ue_cmd,
|
|
|
|
|
"IP address assigned to the UE\n")
|
|
|
|
|
{
|
|
|
|
|
struct pfcp_tool_session *session = vty->index;
|
|
|
|
|
if (osmo_sockaddr_str_from_str2(&session->core.ue_addr, argv[0])) {
|
|
|
|
|
|
|
|
|
|
if (session->kind != UP_GTP_U_TUNEND) {
|
|
|
|
|
vty_out(vty, "%% Error: 'ue ip' makes no sense in a 'tunmap' session%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
if (osmo_sockaddr_str_from_str2(&session->tunend.core.ue_local_addr, argv[0])) {
|
|
|
|
|
vty_out(vty, "Error setting UE IP address%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFUN(s_teid, s_teid_cmd,
|
|
|
|
|
"gtp (access|core) teid local <0-4294967295> remote <0-4294967295>",
|
|
|
|
|
"Setup TEID used in GTP\n"
|
|
|
|
|
"Set the TEIDs towards the ACCESS network (towards the radio network and the actual UE)\n"
|
|
|
|
|
"Set the TEIDs towards the CORE network (towards the internet)\n"
|
|
|
|
|
"Local TEID, which the UPF expects to see in incoming GTP packets\n"
|
|
|
|
|
"Local TEID, when 0 tell the UPF to choose (PFCP: FAR F-TEID: CHOOSE=1)\n"
|
|
|
|
|
"Remote TEID, which the UPF sends out in GTP packets\n"
|
|
|
|
|
"Remote TEID, which the GTP peer has assigned for itself\n")
|
|
|
|
|
#define GTP_ACCESS_CORE_STRS \
|
|
|
|
|
"Setup GTP\n" \
|
|
|
|
|
"Setup GTP towards ACCESS (towards the radio network and the actual UE)\n" \
|
|
|
|
|
"Setup GTP towards CORE (towards the internet)\n"
|
|
|
|
|
#define GTP_LOCAL_STR "Setup GTP on the local side (UPF's local GTP endpoint)\n"
|
|
|
|
|
#define GTP_REMOTE_STR "Setup GTP on the remote side (UPF's remote GTP peer)\n"
|
|
|
|
|
#define F_TEID_STR "Set the fully-qualified TEID, i.e. GTP IP address and TEID\n"
|
|
|
|
|
|
|
|
|
|
DEFUN(s_f_teid, s_f_teid_cmd,
|
|
|
|
|
"gtp (access|core) (local|remote) f-teid A.B.C.D <0-4294967295>",
|
|
|
|
|
GTP_ACCESS_CORE_STRS
|
|
|
|
|
GTP_LOCAL_STR GTP_REMOTE_STR
|
|
|
|
|
F_TEID_STR
|
|
|
|
|
"GTP peer IP address\n"
|
|
|
|
|
"GTP TEID\n")
|
|
|
|
|
{
|
|
|
|
|
struct pfcp_tool_session *session = vty->index;
|
|
|
|
|
struct pfcp_tool_teid_pair *dst;
|
|
|
|
|
if (!strcmp(argv[0], "access"))
|
|
|
|
|
dst = &session->access.teid;
|
|
|
|
|
const char *tun_side = argv[0];
|
|
|
|
|
const char *local_remote = argv[1];
|
|
|
|
|
const char *addr_str = argv[2];
|
|
|
|
|
const char *teid_str = argv[3];
|
|
|
|
|
struct pfcp_tool_gtp_tun_ep *dst;
|
|
|
|
|
|
|
|
|
|
switch (session->kind) {
|
|
|
|
|
case UP_GTP_U_TUNEND:
|
|
|
|
|
if (!strcmp(tun_side, "access")) {
|
|
|
|
|
if (!strcmp(local_remote, "local"))
|
|
|
|
|
dst = &session->tunend.access.local;
|
|
|
|
|
else
|
|
|
|
|
dst = &session->core.teid;
|
|
|
|
|
*dst = (struct pfcp_tool_teid_pair){
|
|
|
|
|
.local = atoi(argv[1]),
|
|
|
|
|
.remote = atoi(argv[2]),
|
|
|
|
|
};
|
|
|
|
|
dst = &session->tunend.access.remote;
|
|
|
|
|
} else {
|
|
|
|
|
vty_out(vty, "%% Error: 'gtp core (local|remote) f-teid': 'tunend' only has GTP on"
|
|
|
|
|
" the 'access' side%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case UP_GTP_U_TUNMAP:
|
|
|
|
|
if (!strcmp(tun_side, "access")) {
|
|
|
|
|
if (!strcmp(local_remote, "local"))
|
|
|
|
|
dst = &session->tunmap.access.local;
|
|
|
|
|
else
|
|
|
|
|
dst = &session->tunmap.access.remote;
|
|
|
|
|
} else {
|
|
|
|
|
if (!strcmp(local_remote, "local"))
|
|
|
|
|
dst = &session->tunmap.core.local;
|
|
|
|
|
else
|
|
|
|
|
dst = &session->tunmap.core.remote;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
OSMO_ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (osmo_sockaddr_str_from_str2(&dst->addr, addr_str)) {
|
|
|
|
|
vty_out(vty, "Error setting GTP IP address from %s%s",
|
|
|
|
|
osmo_quote_cstr_c(OTC_SELECT, addr_str, -1), VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
dst->teid = atoi(teid_str);
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFUN(s_gtp, s_gtp_cmd,
|
|
|
|
|
"gtp (access|core) ip A.B.C.D",
|
|
|
|
|
"Setup GTP peer\n"
|
|
|
|
|
"Set the GTP peer towards the ACCESS network (towards the radio network and the actual UE)\n"
|
|
|
|
|
"Set the GTP peer towards the CORE network (towards the internet)\n"
|
|
|
|
|
"Set the GTP peer IP address, where to send GTP packets to / receive GTP packets from\n"
|
|
|
|
|
"GTP peer IP address\n")
|
|
|
|
|
DEFUN(s_f_teid_choose, s_f_teid_choose_cmd,
|
|
|
|
|
"gtp (access|core) local f-teid choose",
|
|
|
|
|
GTP_ACCESS_CORE_STRS
|
|
|
|
|
GTP_LOCAL_STR
|
|
|
|
|
F_TEID_STR
|
|
|
|
|
"Send F-TEID with CHOOSE=1, i.e. the UPF shall return the local F-TEID in a PFCP Created PDR IE\n")
|
|
|
|
|
{
|
|
|
|
|
struct pfcp_tool_session *session = vty->index;
|
|
|
|
|
struct osmo_sockaddr_str *dst;
|
|
|
|
|
if (!strcmp(argv[0], "access"))
|
|
|
|
|
dst = &session->access.gtp_ip;
|
|
|
|
|
else
|
|
|
|
|
dst = &session->core.gtp_ip;
|
|
|
|
|
if (osmo_sockaddr_str_from_str2(dst, argv[1])) {
|
|
|
|
|
vty_out(vty, "Error setting GTP IP address%s", VTY_NEWLINE);
|
|
|
|
|
const char *tun_side = argv[0];
|
|
|
|
|
struct pfcp_tool_gtp_tun_ep *dst;
|
|
|
|
|
|
|
|
|
|
switch (session->kind) {
|
|
|
|
|
case UP_GTP_U_TUNEND:
|
|
|
|
|
if (!strcmp(tun_side, "access")) {
|
|
|
|
|
dst = &session->tunend.access.local;
|
|
|
|
|
} else {
|
|
|
|
|
vty_out(vty, "%% Error: 'gtp core local choose': 'tunend' only has GTP on"
|
|
|
|
|
" the 'access' side%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case UP_GTP_U_TUNMAP:
|
|
|
|
|
if (!strcmp(tun_side, "access"))
|
|
|
|
|
dst = &session->tunmap.access.local;
|
|
|
|
|
else
|
|
|
|
|
dst = &session->tunmap.core.local;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
OSMO_ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst = (struct pfcp_tool_gtp_tun_ep){};
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -351,6 +409,8 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
|
|
|
|
|
struct osmo_sockaddr ue_addr;
|
|
|
|
|
struct osmo_pfcp_ie_f_seid cp_f_seid;
|
|
|
|
|
|
|
|
|
|
OSMO_ASSERT(session->kind == UP_GTP_U_TUNEND);
|
|
|
|
|
|
|
|
|
|
if (!g_pfcp_tool->ep) {
|
|
|
|
|
vty_out(vty, "Endpoint not configured%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
@@ -361,12 +421,17 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
|
|
|
|
|
else
|
|
|
|
|
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_FORW, true);
|
|
|
|
|
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&session->core.ue_addr, &ue_addr.u.sas)) {
|
|
|
|
|
vty_out(vty, "Error in UE IP%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
#define STR_TO_ADDR(DST, SRC) do { \
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&SRC, &DST.u.sas)) { \
|
|
|
|
|
vty_out(vty, "Error in " #SRC ": " OSMO_SOCKADDR_STR_FMT "%s", \
|
|
|
|
|
OSMO_SOCKADDR_STR_FMT_ARGS(&SRC), VTY_NEWLINE); \
|
|
|
|
|
return CMD_WARNING; \
|
|
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
if (session->access.teid.local == 0) {
|
|
|
|
|
STR_TO_ADDR(ue_addr, session->tunend.core.ue_local_addr);
|
|
|
|
|
|
|
|
|
|
if (session->tunend.access.local.teid == 0) {
|
|
|
|
|
f_teid_access_local = (struct osmo_pfcp_ie_f_teid){
|
|
|
|
|
.choose_flag = true,
|
|
|
|
|
.choose = {
|
|
|
|
|
@@ -376,29 +441,22 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
|
|
|
|
|
} else {
|
|
|
|
|
f_teid_access_local = (struct osmo_pfcp_ie_f_teid){
|
|
|
|
|
.fixed = {
|
|
|
|
|
.teid = session->access.teid.local,
|
|
|
|
|
.teid = session->tunend.access.local.teid,
|
|
|
|
|
.ip_addr = {
|
|
|
|
|
.v4_present = true,
|
|
|
|
|
.v4 = osmo_pfcp_endpoint_get_cfg(g_pfcp_tool->ep)->local_addr,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&session->access.gtp_ip, &f_teid_access_local.fixed.ip_addr.v4.u.sas)) {
|
|
|
|
|
vty_out(vty, "Error in GTP IP towards Access%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
STR_TO_ADDR(f_teid_access_local.fixed.ip_addr.v4, session->tunend.access.local.addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ohc_access = (struct osmo_pfcp_ie_outer_header_creation){
|
|
|
|
|
.teid_present = true,
|
|
|
|
|
.teid = session->access.teid.remote,
|
|
|
|
|
.teid = session->tunend.access.remote.teid,
|
|
|
|
|
.ip_addr.v4_present = true,
|
|
|
|
|
};
|
|
|
|
|
osmo_pfcp_bits_set(ohc_access.desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4, true);
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&session->access.gtp_ip, &ohc_access.ip_addr.v4.u.sas)) {
|
|
|
|
|
vty_out(vty, "Error in GTP IP towards Access%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
STR_TO_ADDR(ohc_access.ip_addr.v4, session->tunend.access.remote.addr);
|
|
|
|
|
|
|
|
|
|
cp_f_seid = (struct osmo_pfcp_ie_f_seid){
|
|
|
|
|
.seid = session->cp_seid,
|
|
|
|
|
@@ -507,7 +565,7 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
|
|
|
|
|
else
|
|
|
|
|
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_FORW, true);
|
|
|
|
|
|
|
|
|
|
if (session->access.teid.local == 0) {
|
|
|
|
|
if (session->tunmap.access.local.teid == 0) {
|
|
|
|
|
f_teid_access_local = (struct osmo_pfcp_ie_f_teid){
|
|
|
|
|
.choose_flag = true,
|
|
|
|
|
.choose = {
|
|
|
|
|
@@ -517,31 +575,25 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
|
|
|
|
|
} else {
|
|
|
|
|
f_teid_access_local = (struct osmo_pfcp_ie_f_teid){
|
|
|
|
|
.fixed = {
|
|
|
|
|
.teid = session->access.teid.local,
|
|
|
|
|
.teid = session->tunmap.access.local.teid,
|
|
|
|
|
.ip_addr = {
|
|
|
|
|
.v4_present = true,
|
|
|
|
|
.v4 = osmo_pfcp_endpoint_get_cfg(g_pfcp_tool->ep)->local_addr,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&session->access.gtp_ip, &f_teid_access_local.fixed.ip_addr.v4.u.sas)) {
|
|
|
|
|
vty_out(vty, "Error in GTP IP towards Access%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
STR_TO_ADDR(f_teid_access_local.fixed.ip_addr.v4, session->tunmap.access.local.addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ohc_access = (struct osmo_pfcp_ie_outer_header_creation){
|
|
|
|
|
.teid_present = true,
|
|
|
|
|
.teid = session->access.teid.remote,
|
|
|
|
|
.teid = session->tunmap.access.remote.teid,
|
|
|
|
|
.ip_addr.v4_present = true,
|
|
|
|
|
};
|
|
|
|
|
osmo_pfcp_bits_set(ohc_access.desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4, true);
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&session->access.gtp_ip, &ohc_access.ip_addr.v4.u.sas)) {
|
|
|
|
|
vty_out(vty, "Error in GTP IP towards Access%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
STR_TO_ADDR(ohc_access.ip_addr.v4, session->tunmap.access.remote.addr);
|
|
|
|
|
|
|
|
|
|
if (session->core.teid.local == 0) {
|
|
|
|
|
if (session->tunmap.core.local.teid == 0) {
|
|
|
|
|
f_teid_core_local = (struct osmo_pfcp_ie_f_teid){
|
|
|
|
|
.choose_flag = true,
|
|
|
|
|
.choose = {
|
|
|
|
|
@@ -551,28 +603,21 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
|
|
|
|
|
} else {
|
|
|
|
|
f_teid_core_local = (struct osmo_pfcp_ie_f_teid){
|
|
|
|
|
.fixed = {
|
|
|
|
|
.teid = session->core.teid.local,
|
|
|
|
|
.teid = session->tunmap.core.local.teid,
|
|
|
|
|
.ip_addr = {
|
|
|
|
|
.v4_present = true,
|
|
|
|
|
.v4 = osmo_pfcp_endpoint_get_cfg(g_pfcp_tool->ep)->local_addr,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&session->core.gtp_ip, &f_teid_core_local.fixed.ip_addr.v4.u.sas)) {
|
|
|
|
|
vty_out(vty, "Error in GTP IP towards Core%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
STR_TO_ADDR(f_teid_core_local.fixed.ip_addr.v4, session->tunmap.core.local.addr);
|
|
|
|
|
}
|
|
|
|
|
ohc_core = (struct osmo_pfcp_ie_outer_header_creation){
|
|
|
|
|
.teid_present = true,
|
|
|
|
|
.teid = session->core.teid.remote,
|
|
|
|
|
.teid = session->tunmap.core.remote.teid,
|
|
|
|
|
.ip_addr.v4_present = true,
|
|
|
|
|
};
|
|
|
|
|
osmo_pfcp_bits_set(ohc_core.desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4, true);
|
|
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&session->core.gtp_ip, &ohc_core.ip_addr.v4.u.sas)) {
|
|
|
|
|
vty_out(vty, "Error in GTP IP towards Core%s", VTY_NEWLINE);
|
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
}
|
|
|
|
|
STR_TO_ADDR(ohc_core.ip_addr.v4, session->tunmap.core.remote.addr);
|
|
|
|
|
|
|
|
|
|
cp_f_seid = (struct osmo_pfcp_ie_f_seid){
|
|
|
|
|
.seid = session->cp_seid,
|
|
|
|
|
@@ -660,7 +705,7 @@ DEFUN(session_tx_est_req, session_tx_est_req_cmd,
|
|
|
|
|
"Set FAR to DROP = 1\n")
|
|
|
|
|
{
|
|
|
|
|
struct pfcp_tool_session *session = vty->index;
|
|
|
|
|
switch (session->gtp_action) {
|
|
|
|
|
switch (session->kind) {
|
|
|
|
|
case UP_GTP_U_TUNEND:
|
|
|
|
|
return session_tunend_tx_est_req(vty, argv, argc);
|
|
|
|
|
case UP_GTP_U_TUNMAP:
|
|
|
|
|
@@ -790,6 +835,6 @@ void pfcp_tool_vty_init_cmds()
|
|
|
|
|
install_element(SESSION_NODE, &session_tx_mod_req_cmd);
|
|
|
|
|
install_element(SESSION_NODE, &session_tx_del_req_cmd);
|
|
|
|
|
install_element(SESSION_NODE, &s_ue_cmd);
|
|
|
|
|
install_element(SESSION_NODE, &s_gtp_cmd);
|
|
|
|
|
install_element(SESSION_NODE, &s_teid_cmd);
|
|
|
|
|
install_element(SESSION_NODE, &s_f_teid_cmd);
|
|
|
|
|
install_element(SESSION_NODE, &s_f_teid_choose_cmd);
|
|
|
|
|
}
|
|
|
|
|
|