fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/41103?usp=email )


Change subject: [REST] Implement EnbErabList
......................................................................

[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 https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/41103?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

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 <[email protected]>

Reply via email to