fixeria has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42433?usp=email )
Change subject: [REST] Add MME source address/port to EnbItem ......................................................................
[REST] Add MME source address/port to EnbItem
The enb_proxy now captures the local address and port of the S1GW-MME SCTP connection (mme_saddr/mme_sport) at comm_up and includes them in conn_info(). Expose this info through the REST API (EnbItem schema), show it as a new column/row in the CLI (enb_list/enb_info).
Change-Id: I15bbddf96ac7d5b6f9962a8d745db58fdec334e7 Related: SYS#7066 --- M contrib/openapi.yaml M contrib/osmo-s1gw-cli.py M doc/manuals/chapters/cli.adoc M doc/manuals/chapters/rest.adoc M priv/openapi.json M src/enb_proxy.erl M src/rest_server.erl 7 files changed, 76 insertions(+), 38 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve fixeria: Looks good to me, approved Jenkins Builder: Verified pespin: Looks good to me, but someone else must approve
diff --git a/contrib/openapi.yaml b/contrib/openapi.yaml index 55448f4..d1aaba9 100644 --- a/contrib/openapi.yaml +++ b/contrib/openapi.yaml @@ -420,15 +420,18 @@ enb_saddr: type: string description: Source (remote) address of the eNB - mme_daddr: - type: string - description: Destination (remote) address of the MME enb_sport: type: integer description: Source (remote) port of the eNB-S1GW connection + mme_saddr: + type: string + description: Source (local) address of the S1GW-MME connection mme_sport: type: integer description: Source (local) port of the S1GW-MME connection + mme_daddr: + type: string + description: Destination (remote) address of the MME mme_dport: type: integer description: Destination (remote) port of the S1GW-MME connection diff --git a/contrib/osmo-s1gw-cli.py b/contrib/osmo-s1gw-cli.py index 3878708..12079be 100755 --- a/contrib/osmo-s1gw-cli.py +++ b/contrib/osmo-s1gw-cli.py @@ -395,17 +395,28 @@ self.iface.mme_delete(self.gen_mme_id(opts))
@staticmethod - def enb_list_item(item: dict) -> dict: + def enb_list_item_addr_port(item: dict, enb_mme: str, sd: str) -> str: + ''' Generate an 'addr:port (aid)' string for the given EnbItem ''' + addr = item.get(f'{enb_mme}_{sd}addr') + port = item.get(f'{enb_mme}_{sd}port') + if (addr is None) or (port is None): + return '' + aid = item.get(f'{enb_mme}_sctp_aid') + if aid is None: + return f'{addr}:{port}' + return f'{addr}:{port} ({aid})' + + @classmethod + def enb_list_item(cls, item: dict) -> dict: ''' Generate a table row for the given eNB ''' - enb_addr = lambda item: '{enb_saddr}:{enb_sport} ({enb_sctp_aid})'.format(**item) - mme_addr = lambda item: '{mme_daddr}:{mme_dport} ({mme_sctp_aid})'.format(**item) return { 'eNB handle': item.get('handle'), 'PID': item.get('pid'), 'Global-eNB-ID': item.get('genb_id', '(unknown)'), 'State': item.get('state'), - 'eNB addr:port (aid)': enb_addr(item) if 'enb_saddr' in item else None, - 'MME addr:port (aid)': mme_addr(item) if 'mme_daddr' in item else None, + 'eNB saddr:sport (aid)': cls.enb_list_item_addr_port(item, 'enb', 's'), + 'MME saddr:sport (aid)': cls.enb_list_item_addr_port(item, 'mme', 's'), + 'MME daddr:dport (aid)': cls.enb_list_item_addr_port(item, 'mme', 'd'), 'MME name': item.get('mme_name'), 'Uptime (s)': item.get('uptime'), '# E-RABs': item.get('erab_count'), diff --git a/doc/manuals/chapters/cli.adoc b/doc/manuals/chapters/cli.adoc index f24016b..2daf0b4 100644 --- a/doc/manuals/chapters/cli.adoc +++ b/doc/manuals/chapters/cli.adoc @@ -285,11 +285,11 @@
---- OsmoS1GW# enb_list -| handle | PID | Global-eNB-ID | State | eNB addr:port (aid) | MME addr:port (aid) | MME name | Uptime | E-RABs | -|----------|-----------|---------------|-----------|-------------------------|-------------------------|----------|----------|----------| -| 0 | <0.699.0> | 001-01-0 | connected | 127.0.1.10:56767 (5706) | 127.0.2.10:36412 (5707) | mme0 | 418 | 0 | -| 1 | <0.701.0> | 001-01-1 | connected | 127.0.1.10:54140 (5710) | 127.0.2.10:36412 (5711) | mme0 | 33 | 3 | -| 2 | <0.703.0> | 001-01-2 | connected | 127.0.1.10:34076 (5714) | 127.0.2.10:36412 (5715) | mme0 | 3600 | 20 | +| handle | PID | Global-eNB-ID | State | eNB saddr:sport (aid) | MME saddr:sport (aid) | MME daddr:dport (aid) | MME name | Uptime | E-RABs | +|----------|-----------|---------------|-----------|-------------------------|------------------------|-------------------------|----------|----------|----------| +| 0 | <0.699.0> | 001-01-0 | connected | 127.0.1.10:56767 (5706) | 127.0.2.1:34650 (5707) | 127.0.2.10:36412 (5707) | mme0 | 418 | 0 | +| 1 | <0.701.0> | 001-01-1 | connected | 127.0.1.10:54140 (5710) | 127.0.2.1:34651 (5711) | 127.0.2.10:36412 (5711) | mme0 | 33 | 3 | +| 2 | <0.703.0> | 001-01-2 | connected | 127.0.1.10:34076 (5714) | 127.0.2.1:34652 (5715) | 127.0.2.10:36412 (5715) | mme0 | 3600 | 20 | ----
==== `enb_info` @@ -315,17 +315,18 @@
---- OsmoS1GW# enb_info -H 8 -| Parameter | Value | -|---------------------|-------------------------| -| eNB handle | 8 | -| PID | <0.715.0> | -| Global-eNB-ID | 001-01-8 | -| State | connected | -| eNB addr:port (aid) | 127.0.1.10:57362 (5734) | -| MME addr:port (aid) | 127.0.2.10:36412 (5745) | -| MME name | mme0 | -| Uptime (s) | 521 | -| # E-RABs | 99 | +| Parameter | Value | +|-----------------------|-------------------------| +| eNB handle | 8 | +| PID | <0.715.0> | +| Global-eNB-ID | 001-01-8 | +| State | connected | +| eNB saddr:sport (aid) | 127.0.1.10:57362 (5734) | +| MME saddr:sport (aid) | 127.0.2.1:73421 (5745) | +| MME daddr:dport (aid) | 127.0.2.10:36412 (5745) | +| MME name | mme0 | +| Uptime (s) | 521 | +| # E-RABs | 99 | ----
==== `enb_delete` diff --git a/doc/manuals/chapters/rest.adoc b/doc/manuals/chapters/rest.adoc index 7c1383b..cc74ba1 100644 --- a/doc/manuals/chapters/rest.adoc +++ b/doc/manuals/chapters/rest.adoc @@ -259,9 +259,10 @@ "enb_sport": 56767, "enb_sctp_aid": 5706, "mme_name": "mme0", + "mme_saddr": "192.168.2.1", + "mme_sport": 34500, "mme_daddr": "192.168.2.10", "mme_dport": 36412, - "mme_sport": 34500, "mme_sctp_aid": 5707, "uptime": 418, "erab_count": 3 @@ -278,8 +279,8 @@ `enb_saddr` / `enb_sport`:: Source address and port of the eNB's SCTP connection. `enb_sctp_aid`:: SCTP association ID of the eNB-S1GW connection. `mme_name`:: Name of the selected MME (from the MME pool). +`mme_saddr` / `mme_sport`:: Local address and port of the S1GW-MME SCTP connection. `mme_daddr` / `mme_dport`:: Destination address and port of the MME. -`mme_sport`:: Local source port of the S1GW-MME SCTP connection. `mme_sctp_aid`:: SCTP association ID of the S1GW-MME connection. `uptime`:: Seconds since the eNB connected. `erab_count`:: Number of currently active E-RABs for this eNB. diff --git a/priv/openapi.json b/priv/openapi.json index 59c9676..bcec82b 100644 --- a/priv/openapi.json +++ b/priv/openapi.json @@ -622,18 +622,22 @@ "type": "string", "description": "Source (remote) address of the eNB" }, - "mme_daddr": { - "type": "string", - "description": "Destination (remote) address of the MME" - }, "enb_sport": { "type": "integer", "description": "Source (remote) port of the eNB-S1GW connection" }, + "mme_saddr": { + "type": "string", + "description": "Source (local) address of the S1GW-MME connection" + }, "mme_sport": { "type": "integer", "description": "Source (local) port of the S1GW-MME connection" }, + "mme_daddr": { + "type": "string", + "description": "Destination (remote) address of the MME" + }, "mme_dport": { "type": "integer", "description": "Destination (remote) port of the S1GW-MME connection" diff --git a/src/enb_proxy.erl b/src/enb_proxy.erl index c76ac42..17296bd 100644 --- a/src/enb_proxy.erl +++ b/src/enb_proxy.erl @@ -60,12 +60,15 @@
-type conn_info() :: #{handler := pid(), enb_aid := gen_sctp:assoc_id(), - mme_aid => gen_sctp:assoc_id() - %% TODO: add mme_saddr / mme_sport + mme_aid => gen_sctp:assoc_id(), + mme_saddr => inet:ip_address(), + mme_sport => inet:port_number() }.
-record(state, {enb_aid :: gen_sctp:assoc_id(), mme_aid :: undefined | gen_sctp:assoc_id(), + mme_saddr :: undefined | inet:ip_address(), + mme_sport :: undefined | inet:port_number(), enb_conn_info :: sctp_server:conn_info(), s1setup_req :: undefined | binary(), tried_mmes :: [mme_registry:mme_name()], @@ -117,6 +120,8 @@ {ok, Pid} = s1ap_proxy:start_link(self()), {ok, wait_s1setup_req, #state{enb_aid = maps:get(aid, EnbConnInfo), + mme_saddr = undefined, + mme_sport = undefined, enb_conn_info = EnbConnInfo, enb_handle = EnbHandle, tried_mmes = [], @@ -206,6 +211,8 @@ {next_state, ?FUNCTION_NAME, %% loop transition to enable state_timeout S#state{sock = Sock, mme_aid = undefined, + mme_saddr = undefined, + mme_sport = undefined, tried_mmes = [MmeName | TriedMMEs]}, [{state_timeout, 2_000, conn_est_timeout}]}; error -> @@ -241,12 +248,15 @@ MmeName = hd(S#state.tried_mmes), case ConnState of comm_up -> + {ok, {MmeLAddr, MmeLPort}} = inet:sockname(Socket), ?LOG_NOTICE("MME ~p: connection (id=~p, ~p:~p) established", [MmeName, Aid, MmeAddr, MmePort]), %% send the S1 SETUP REQUEST PDU to the MME sctp_send_from_enb(S#state.s1setup_req, S#state{mme_aid = Aid}), - {next_state, wait_s1setup_rsp, S#state{mme_aid = Aid}}; + {next_state, wait_s1setup_rsp, S#state{mme_aid = Aid, + mme_saddr = MmeLAddr, + mme_sport = MmeLPort}}; _ -> ?LOG_NOTICE("MME ~p: connection establishment failed: ~p", [MmeName, ConnState]), @@ -467,7 +477,9 @@ conn_info(S) -> Info = #{handler => S#state.handler, enb_aid => S#state.enb_aid, - mme_aid => S#state.mme_aid}, + mme_aid => S#state.mme_aid, + mme_saddr => S#state.mme_saddr, + mme_sport => S#state.mme_sport}, maps:filter(fun(_K, V) -> V =/= undefined end, Info).
diff --git a/src/rest_server.erl b/src/rest_server.erl index 3b14b86..0107427 100644 --- a/src/rest_server.erl +++ b/src/rest_server.erl @@ -461,10 +461,16 @@ enb_item_add_mme_conn_info(M0, #{mme_conn_info := ConnInfo}) -> Pid = maps:get(handler, ConnInfo), ERABs = s1ap_proxy:fetch_erab_list(Pid), - %% TODO: mme_sport (source port) is not yet available in conn_info() - M0#{mme_sctp_aid => maps:get(mme_aid, ConnInfo), - erab_count => length(ERABs) - }; + M1 = M0#{erab_count => length(ERABs)}, + %% mme_aid/mme_saddr/mme_sport are only present once the MME SCTP + %% connection is fully established (comm_up); handle them together. + case maps:find(mme_aid, ConnInfo) of + {ok, Aid} -> + M1#{mme_sctp_aid => Aid, + mme_saddr => inet:ntoa(maps:get(mme_saddr, ConnInfo)), + mme_sport => maps:get(mme_sport, ConnInfo)}; + error -> M1 + end;
enb_item_add_mme_conn_info(M0, _) -> M0.