fixeria has uploaded this change for review.

View Change

[REST] Implement EnbErabList

Change-Id: I846974dd79e737acaac17918d18da55967a9abf2
Related: SYS#7066
---
M contrib/openapi.yaml
M contrib/osmo-s1gw-cli.py
M priv/openapi.json
M src/rest_server.erl
4 files changed, 275 insertions(+), 1 deletion(-)

git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/03/41103/1
diff --git a/contrib/openapi.yaml b/contrib/openapi.yaml
index 24bc2c8..0041274 100644
--- a/contrib/openapi.yaml
+++ b/contrib/openapi.yaml
@@ -92,6 +92,22 @@
'404':
description: Unsuccessful outcome (eNB not found)

+ /enb/{EnbId}/erab-list:
+ get:
+ summary: Get E-RAB list for a specific eNB
+ operationId: EnbErabList
+ parameters:
+ - $ref: '#/components/parameters/EnbId'
+ responses:
+ '200':
+ description: Successful outcome (E-RAB list)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErabList'
+ '404':
+ description: Unsuccessful outcome (eNB not found)
+
components:
responses:
OperationResult:
@@ -248,3 +264,62 @@
mme_sctp_aid:
type: integer
description: SCTP association identifier of the S1GW-MME connection
+
+ ErabList:
+ type: array
+ items:
+ $ref: '#/components/schemas/ErabItem'
+
+ FTEID:
+ type: object
+ required:
+ - teid
+ - tla
+ properties:
+ teid:
+ type: integer
+ description: GTP-U TEID
+ tla:
+ type: string
+ description: GTP-U TLA (Transport Layer Address)
+
+ ErabItem:
+ type: object
+ required:
+ - mme_ue_id
+ - erab_id
+ - state
+ - pid
+ properties:
+ mme_ue_id:
+ type: integer
+ description: MME-UE-S1AP-ID
+ erab_id:
+ type: integer
+ description: E-RAB-ID
+ state:
+ type: string
+ description: E-RAB FSM state
+ example: erab_wait_release_rsp
+ pid:
+ type: string
+ pattern: '^<[0-9]+\.[0-9]+\.[0-9]+>$'
+ description: E-RAB FSM process ID
+ pfcp_lseid:
+ type: integer
+ description: PFCP SEID (local)
+ pfcp_rseid:
+ type: integer
+ description: PFCP SEID (remote)
+ f_teid_u2c:
+ $ref: '#/components/schemas/FTEID'
+ description: GTP-U F-TEID for UPF -> Core
+ f_teid_c2u:
+ $ref: '#/components/schemas/FTEID'
+ description: GTP-U F-TEID for UPF <- Core
+ f_teid_a2u:
+ $ref: '#/components/schemas/FTEID'
+ description: GTP-U F-TEID for UPF <- Access
+ f_teid_u2a:
+ $ref: '#/components/schemas/FTEID'
+ description: GTP-U F-TEID for UPF -> Access
diff --git a/contrib/osmo-s1gw-cli.py b/contrib/osmo-s1gw-cli.py
index 84036d7..cb77709 100755
--- a/contrib/osmo-s1gw-cli.py
+++ b/contrib/osmo-s1gw-cli.py
@@ -111,6 +111,11 @@
with self.send_get_req(f'enb/{enb_id}') as f:
return json.load(f)

+ def enb_erab_list(self, enb_id: str) -> RESTResponse:
+ ''' EnbErabList :: Get E-RAB list for a specific eNB '''
+ with self.send_get_req(f'enb/{enb_id}/erab-list') as f:
+ return json.load(f)
+

class OsmoS1GWCli(cmd2.Cmd):
DESC = 'Interactive CLI for OsmoS1GW'
@@ -263,6 +268,35 @@
data = self.iface.enb_info(enb_id)
self.enb_list_print([data])

+ @staticmethod
+ def erab_list_item(item: dict) -> dict:
+ f_teid = lambda params: '0x{teid:08x}@{tla}'.format(**params)
+ seid = lambda val: f'0x{val:016x}'
+ return {
+ 'PID': item.get('pid'),
+ 'MME-UE-S1AP-ID': item.get('mme_ue_id'),
+ 'E-RAB-ID': item.get('erab_id'),
+ 'State': item.get('state'),
+ 'SEID (local)': seid(item.get('pfcp_lseid')) if 'pfcp_lseid' in item else None,
+ 'SEID (remote)': seid(item.get('pfcp_rseid')) if 'pfcp_rseid' in item else None,
+ 'U2C F-TEID': f_teid(item.get('f_teid_u2c')) if 'f_teid_u2c' in item else None,
+ 'C2U F-TEID': f_teid(item.get('f_teid_c2u')) if 'f_teid_c2u' in item else None,
+ 'A2U F-TEID': f_teid(item.get('f_teid_a2u')) if 'f_teid_a2u' in item else None,
+ 'U2A F-TEID': f_teid(item.get('f_teid_u2a')) if 'f_teid_u2a' in item else None,
+ }
+
+ def erab_list_print(self, items: list[dict]) -> None:
+ self.poutput(tabulate.tabulate(map(self.erab_list_item, items),
+ headers='keys', tablefmt='github'))
+
+ @cmd2.with_argparser(enb_id_parser)
+ @cmd2.with_category(CAT_ENB)
+ def do_enb_erab_list(self, opts) -> None:
+ ''' Get E-RAB list for a specific eNB '''
+ enb_id = self.gen_enb_id(opts)
+ data = self.iface.enb_erab_list(enb_id)
+ self.erab_list_print(data)
+

ap = argparse.ArgumentParser(prog='osmo-s1gw-cli', description=OsmoS1GWCli.DESC)

diff --git a/priv/openapi.json b/priv/openapi.json
index 3e8f22e..07a11b8 100644
--- a/priv/openapi.json
+++ b/priv/openapi.json
@@ -140,6 +140,32 @@
}
}
}
+ },
+ "/enb/{EnbId}/erab-list": {
+ "get": {
+ "summary": "Get E-RAB list for a specific eNB",
+ "operationId": "EnbErabList",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/EnbId"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful outcome (E-RAB list)",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErabList"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unsuccessful outcome (eNB not found)"
+ }
+ }
+ }
}
},
"components": {
@@ -358,6 +384,82 @@
"description": "SCTP association identifier of the S1GW-MME connection"
}
}
+ },
+ "ErabList": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ErabItem"
+ }
+ },
+ "FTEID": {
+ "type": "object",
+ "required": [
+ "teid",
+ "tla"
+ ],
+ "properties": {
+ "teid": {
+ "type": "integer",
+ "description": "GTP-U TEID"
+ },
+ "tla": {
+ "type": "string",
+ "description": "GTP-U TLA (Transport Layer Address)"
+ }
+ }
+ },
+ "ErabItem": {
+ "type": "object",
+ "required": [
+ "mme_ue_id",
+ "erab_id",
+ "state",
+ "pid"
+ ],
+ "properties": {
+ "mme_ue_id": {
+ "type": "integer",
+ "description": "MME-UE-S1AP-ID"
+ },
+ "erab_id": {
+ "type": "integer",
+ "description": "E-RAB-ID"
+ },
+ "state": {
+ "type": "string",
+ "description": "E-RAB FSM state",
+ "example": "erab_wait_release_rsp"
+ },
+ "pid": {
+ "type": "string",
+ "pattern": "^<[0-9]+\\.[0-9]+\\.[0-9]+>$",
+ "description": "E-RAB FSM process ID"
+ },
+ "pfcp_lseid": {
+ "type": "integer",
+ "description": "PFCP SEID (local)"
+ },
+ "pfcp_rseid": {
+ "type": "integer",
+ "description": "PFCP SEID (remote)"
+ },
+ "f_teid_u2c": {
+ "$ref": "#/components/schemas/FTEID",
+ "description": "GTP-U F-TEID for UPF -> Core"
+ },
+ "f_teid_c2u": {
+ "$ref": "#/components/schemas/FTEID",
+ "description": "GTP-U F-TEID for UPF <- Core"
+ },
+ "f_teid_a2u": {
+ "$ref": "#/components/schemas/FTEID",
+ "description": "GTP-U F-TEID for UPF <- Access"
+ },
+ "f_teid_u2a": {
+ "$ref": "#/components/schemas/FTEID",
+ "description": "GTP-U F-TEID for UPF -> Access"
+ }
+ }
}
}
}
diff --git a/src/rest_server.erl b/src/rest_server.erl
index f546ad9..2f805da 100644
--- a/src/rest_server.erl
+++ b/src/rest_server.erl
@@ -38,7 +38,8 @@
pfcp_assoc_state/1,
pfcp_heartbeat/1,
enb_list/1,
- enb_info/1
+ enb_info/1,
+ enb_erab_list/1
]).

-include_lib("kernel/include/logger.hrl").
@@ -105,6 +106,20 @@
end.


+%% EnbErabList :: Get E-RAB list for a specific eNB
+enb_erab_list(#{path_parameters := PP}) ->
+ [{<< "EnbId" >>, << ID/bytes >>}] = PP,
+ case fetch_enb_info(ID) of
+ [EnbInfo | _] ->
+ Rsp = fetch_erab_list(EnbInfo),
+ {200, [], Rsp};
+ [] ->
+ {404, [], undefined};
+ error ->
+ {500, [], undefined}
+ end.
+
+
%% ------------------------------------------------------------------
%% private API
%% ------------------------------------------------------------------
@@ -230,6 +245,54 @@
error.


+-spec fetch_erab_list(enb_registry:enb_info()) -> [map()].
+fetch_erab_list(#{mme_conn_info := ConnInfo}) ->
+ Pid = maps:get(handler, ConnInfo), %% s1ap_proxy process pid
+ ERABs = s1ap_proxy:fetch_erab_list(Pid),
+ lists:map(fun erab_list_item/1, ERABs);
+
+fetch_erab_list(_) -> [].
+
+
+-spec erab_list_item({term(), pid()}) -> map().
+erab_list_item({_, Pid}) ->
+ %% XXX: E-RAB FSM process might be dead here
+ Info = erab_fsm:fetch_info(Pid),
+ {MmeUeId, ErabId} = maps:get(uid, Info),
+ M0 = #{mme_ue_id => MmeUeId,
+ erab_id => ErabId,
+ state => maps:get(state, Info),
+ pid => pid_to_list(Pid)},
+ M1 = erab_list_item_add_seid(Info, M0),
+ M2 = erab_list_item_add_f_teid(f_teid_u2c, Info, M1),
+ M3 = erab_list_item_add_f_teid(f_teid_c2u, Info, M2),
+ M4 = erab_list_item_add_f_teid(f_teid_a2u, Info, M3),
+ M5 = erab_list_item_add_f_teid(f_teid_u2a, Info, M4),
+ rsp_map(M5).
+
+
+-spec erab_list_item_add_seid(erab_fsm:erab_info(), map()) -> map().
+erab_list_item_add_seid(Info, M0) ->
+ %% local SEID is always known/present
+ M1 = M0#{pfcp_lseid => maps:get(seid_loc, Info)},
+ %% remote SEID may or may not be known/present
+ case maps:find(seid_rem, Info) of
+ {ok, SEID} -> M1#{pfcp_rseid => SEID};
+ error -> M1
+ end.
+
+
+-spec erab_list_item_add_f_teid(atom(), erab_fsm:erab_info(), map()) -> map().
+erab_list_item_add_f_teid(Key, Info, M0) ->
+ case maps:find(Key, Info) of
+ {ok, {TEID, AddrBin}} ->
+ Addr = list_to_tuple(binary_to_list(AddrBin)),
+ M0#{Key => #{teid => TEID,
+ tla => inet:ntoa(Addr)}};
+ error -> M0
+ end.
+
+
-spec parse_pid(binary() | list()) -> pid().
parse_pid(Data) when is_binary(Data) ->
parse_pid(binary_to_list(Data));

To view, visit change 41103. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I846974dd79e737acaac17918d18da55967a9abf2
Gerrit-Change-Number: 41103
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de>