--- title: Open5GS JSON infoAPI for accessing UE, gNB/eNB, and session data --- ## How it works Open5GS has a lightweight HTTP server (already used for `/metrics`) embedded in some NFs. New optional JSON endpoints were added: | NF | Endpoint | Content | | --- | --- | --- | | SMF | /pdu-info | All currently connected UEs + their PDU sessions (IMSI/SUPI, DNN, IPs, S-NSSAI, QoS, state, etc.) | | AMF | /gnb-info | All currently connected gNBs and their supported TAs, PLMNs, SCTP info, number of UEs | | AMF | /ue-info | All currently connected NR UEs and their info, active gNB, tai, security, slices, am_policy | | MME | /enb-info | All currently connected eNBs and their supported TAs, PLMNs, SCTP info, number of UEs | | MME | /ue-info | All currently connected LTE UEs and their info, active eNB, tai, pdn info | They are exposed on the same HTTP port used by Prometheus metrics (default `:9090`). To reduce processor load when there are a large number of devices, the API includes a pager that limits output. `/ue-info?page=0&page_size=100` page in the range 0-n (0 is default), `page=-1` to avoid paging `page_size=100` (default and MAX) --- ## How to enable You need to build Open5GS from the latest `main` branch: ``` git clone https://github.com/open5gs/open5gs.git cd open5gsgit checkout mainmeson build --prefix=`pwd`/installninja -C build install ``` ## How to use ### Get info about PDUs from all UEs connected to 5G NR and LTE basestation contains session info as APN/DNN, IP addresses, slice info, QoS info, PDU/PDN_state and UE_activity status ``` curl -s "http://127.0.0.4:9090/pdu-info" |jq . ``` ##### Example response ``` { "items": [ { "supi": "imsi-231510000114763", "pdu": [ { "psi": 1, "dnn": "internet", "ipv4": "10.45.0.11", "snssai": { "sst": 1, "sd": "ffffff" }, "qos_flows": [ { "qfi": 1, "5qi": 9 } ], "pdu_state": "inactive" } ], "ue_activity": "idle" } ], "pager": { "page": 0, "page_size": 100, "count": 1, } } ``` ### Get all 5G NR connected UEs (from AMF) contains the UE_ID as SUPI, SUCI, PEI, GUTI, TMSI, GNB_ID to which the UE is connected, AMBR, slices .. ``` curl -s "http://127.0.0.5:9090/ue-info" |jq . ``` ##### Example response ``` { "items": [ { "supi": "imsi-001010000056492", "suci": "suci-0-001-01-0000-1-1-85731c4241d466407311a85135e914987944f361550f13f4532e29bdc5859548a363cc1a81798bb4cc59f2b4db", "pei": "imeisv-3535938300494715", "cm_state": "connected", "guti": "00101-030080-CC00007AB", "m_tmsi": 3221227435, "gnb": { "ostream_id": 1, "amf_ue_ngap_id": 2, "ran_ue_ngap_id": 39, "gnb_id": 100, "cell_id": 1 }, "location": { "timestamp": 1758733375895512, "nr_tai": { "plmn": "99970", "tac_hex": "000001", "tac": 1 }, "nr_cgi": { "plmn": "99970", "nci": 1638401, "gnb_id": 100, "cell_id": 1 }, "last_visited_plmn_id": "000000" }, "msisdn": [], "security": { "valid": 1, "enc": "nea2", "int": "nia2" }, "ambr": { "downlink": 1000000000, "uplink": 1000000000 }, "pdu_sessions": [], "pdu_sessions_count": 0, "requested_slices": [ { "sst": 1, "sd": "ffffff" } ], "allowed_slices": [ { "sst": 1, "sd": "ffffff" } ], "requested_slices_count": 1, "allowed_slices_count": 1, "am_policy_features": 4, "am_policy_features_info": { "hex": "0x0000000000000004", "bits": [ 2 ], "labels": [ "QoS Policy Control" ] } } ], "pager": { "page": 0, "page_size": 100, "count": 2 } } ``` ### Get all LTE connected UEs ( from MME ) contains the ENB_ID to which the UE is connected ``` curl -s "http://127.0.0.2:9090/ue-info?" |jq . ``` ##### Example response ``` { "items": [ { "supi": "999700000021632", "domain": "EPS", "rat": "E-UTRA", "cm_state": "connected", "enb": { "ostream_id": 3, "mme_ue_ngap_id": 3, "ran_ue_ngap_id": 9, "enb_id": 264040, "cell_id": 67594275 }, "location": { "tai": { "plmn": "99970", "tac_hex": "0001", "tac": 1 } }, "ambr": { "downlink": 1000000000, "uplink": 1000000000 }, "pdn": [ { "apn": "internet", "qos_flows": [ { "ebi": 5 } ], "qci": 9, "ebi": 5, "bearer_count": 1, "pdu_state": "active" } ], "pdn_count": 1 } ], "pager": { "page": 0, "page_size": 100, "count": 1 } } ``` ### Get all connected gNBs (from AMF) contains gNB info and number of RRC connected UEs ``` curl -s "http://127.0.0.5:9090/gnb-info?" |jq . ``` ##### Example response ``` { "items": [ { "gnb_id": 100, "plmn": "99970", "network": { "amf_name": "efire-amf0", "ngap_port": 38412 }, "ng": { "sctp": { "peer": "[192.168.168.100]:60110", "max_out_streams": 2, "next_ostream_id": 1 }, "setup_success": true }, "supported_ta_list": [ { "tac": "000001", "bplmns": [ { "plmn": "99970", "snssai": [ { "sst": 1, "sd": "ffffff" } ] }, { "plmn": "99971", "snssai": [ { "sst": 2, "sd": "000000" } ] } ] } ], "num_connected_ues": 2 } ], "pager": { "page": 0, "page_size": 100, "count": 1 } } ``` ### Get all connected eNBs (from MME) contains eNB info and number of connected UEs ``` curl -s "http://127.0.0.2:9090/enb-info?" |jq . ``` ##### Example response ``` { "items": [ { "enb_id": 264040, "plmn": "99970", "network": { "mme_name": "efire-mme0" }, "s1": { "sctp": { "peer": "[192.168.168.254]:36412", "max_out_streams": 10, "next_ostream_id": 3 }, "setup_success": true }, "supported_ta_list": [ { "tac": "0001", "plmn": "99970" } ], "num_connected_ues": 1 } ], "pager": { "page": 0, "page_size": 100, "count": 1 } } ``` Using a suitable filter in jq, the output can be simplified and adapted to the desired form. AMF/ue-info sorted on supi ( page=-1 to avoid paging and show all UEs ) ``` ./amf_ue_sort.sh supi cm-state gnb_id dnn imsi-001010000056492 connected 100 internet imsi-231510000114763 connected 100 internet imsi-999700000021630 connected 100 internet imsi-999700000083810 idle 100 internet imsi-999700000114762 idle 100 internet ``` ``` curl -s "http://127.0.0.5:9090/ue-info?page=-1" \ | jq -r ' # Unwrap common list keys or accept a bare array/object ( .ue_infos // .items // .data // .results // .list // . ) | (if type=="array" then . else [.] end) | sort_by(.supi // "")| group_by(.supi)| map({supi: (.[0].supi // "-"), cm: (if any(.[]; .cm_state == "connected") then "connected" else (.[-1].cm_state // "-") end), gnb_id: ( ( [ .[] | select(.cm_state=="connected") | (.gnb.gnb_id? // .location.nr_cgi.gnb_id?) ] | map(select(.!=null)) | .[0] ) // ( [ .[] | (.gnb.gnb_id? // .location.nr_cgi.gnb_id?) ] | map(select(.!=null)) | .[0] ) // "-" ), dnns: ( [ .[].pdu_sessions[]?.dnn ] | map(select(. != null and . != "")) | unique | sort | if length==0 then ["-"] else . end ) }) | sort_by( ( .supi | tostring | sub("^imsi-"; "") | tonumber? ) // 0 ) ``` AMF/gnb-info ``` ./amf_gnb_sort.sh gnb_id peer plmn num_connected_ues 100 [192.168.168.100]:60110 99970 1 411 [192.168.168.99]:34349 99970 0 ``` ``` curl -s "http://127.0.0.5:9090/gnb-info" \ | jq -r ' ( .items // .gnbs // .data // .results // .list // . ) | (if type=="array" then . else [.] end) | sort_by(.gnb_id // 0) | (["gnb_id","peer","plmn","num_connected_ues"]), ( .[] | [ (.gnb_id // "-"), (.ng?.sctp?.peer // "-"), (.plmn // "-"), ((.num_connected_ues // 0) | tostring) ]) | @tsv ' | column -s $'\t' -t ``` MME/enb-info ``` ./mme_enb_sort.sh enb_id peer plmn num_connected_ues 264040 [192.168.168.254]:36412 99970 1 ``` ``` curl -s "http://127.0.0.2:9090/enb-info" \ | jq -r ' ( .items // .enbs // .data // .results // .list // . ) | (if type=="array" then . else [.] end) | sort_by(.enb_id // 0) | (["enb_id","peer","plmn","num_connected_ues"]), ( .[] | [ (.enb_id // "-"), (.s1?.sctp?.peer // "-"), (.plmn // "-"), ((.num_connected_ues // 0) | tostring) ]) | @tsv ' | column -s $'\t' -t ``` MME/ue-info ``` ./mme_ue_sort.sh supi cm-state enb_id apn 001010000056492 connected 264040 internet 999700000021632 connected 264040 internet 999700000083811 connected 264040 internet ``` ``` curl -s "http://127.0.0.2:9090/ue-info?page=-1" \ | jq -r ' ( .items // .ue_infos // .data // .results // .list // . ) | (if type=="array" then . else [.] end) | map(select(((.rat? // "") | test("^(E-?UTRA|LTE)$"; "i")) or((.domain? // "") | test("^EPS$"; "i")))) | sort_by(.supi // "")| group_by(.supi)| map({supi: (.[0].supi // "-"),cm: (if any(.[]; .cm_state == "connected") then "connected"else (.[-1].cm_state // "-") end),enb_id: (( [ .[] | select(.cm_state=="connected") | .enb.enb_id? ]| map(select(.!=null)) | .[0] )// ( [ .[] | .enb.enb_id? ] | map(select(.!=null)) | .[0] )// "-"),apns: ([ .[].pdn[]?.apn ]| map(select(. != null and . != ""))| unique | sort| if length==0 then ["-"] else . end)}) | sort_by( ( .supi | tostring | sub("^imsi-"; "") | tonumber? ) // 0 ) ``` SMF/pdu-info ``` ./smf_pdu_sort.sh supi ue_activity dnn ipv4/ipv6 pdu_state imsi-001010000056492 active internet 10.45.0.59 active imsi-231510000114763 idle internet 10.45.0.52 inactive imsi-999700000021630 idle internet 10.45.250.250 inactive 999700000021632 unknown internet 10.45.0.8 unknown imsi-999700000083810 idle internet 10.45.0.12 inactive imsi-999700000114762 idle internet 10.45.0.10 inactive ``` ``` curl -s "http://127.0.0.4:9090/pdu-info?page=-1" \ | jq -r ' ( .items // .ue_infos // .data // .results // .list // . ) | (if type=="array" then . else [.] end) as $arr | ($arr | map((.pdu // []) | length) | max // 0) as $maxp | ( ["supi","ue_activity"]+ ([ range(0; $maxp) | "dnn","ipv4/ipv6","pdu_state" ]) ), # Rows ( $arr | sort_by( ( .supi | tostring | sub("^imsi-"; "") | tonumber? ) // 0 ) | .[] | . as $ue | ( $ue.pdu // [] | sort_by(.psi // .ebi // 0) ) as $pdus | [ ($ue.supi // "-"), ($ue.ue_activity // "-") ] + ( $pdus | map([ (.dnn // .apn // "-"), ( ([.ipv4?, .ipv6?] | map(select(.!=null and .!="")) | join("/") ) | if .=="" then "-" else . end ), (.pdu_state // "-") ]) | add // [] ) + ( [ range( ( ($pdus|length) * 3 ); ($maxp * 3) ) | "-" ] ) ) ```