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


Change subject: erab_fsm: implement handling of GTP-U address
......................................................................

erab_fsm: implement handling of GTP-U address

Change-Id: Ifdc492c41266d07d0e951dcdcc1e4ba74da0b13b
---
M src/erab_fsm.erl
M test/erab_fsm_test.erl
M test/pfcp_mock.erl
M test/pfcp_mock.hrl
4 files changed, 87 insertions(+), 57 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw 
refs/changes/04/37804/1

diff --git a/src/erab_fsm.erl b/src/erab_fsm.erl
index abc25b1..d2aa065 100644
--- a/src/erab_fsm.erl
+++ b/src/erab_fsm.erl
@@ -64,12 +64,17 @@
 -define(ERAB_T_SESSION_DELETE, 2_000).

 -type teid() :: 0..16#ffffffff.
+-type addr() :: << _:32 >> | << _:128 >>.
+
+-type teid_addr() :: {teid(), %% GTP-U TEID
+                      addr()  %% GTP-U Transport Layer Address
+                     }.

 -record(erab_state, {from :: undefined | gen_statem:from(), %% destination to 
use when replying
-                     teid_upf2core :: undefined | teid(), %% TEID to be used 
in UPF -> Core
-                     teid_core2upf :: undefined | teid(), %% TEID to be used 
in UPF <- Core
-                     teid_acc2upf :: undefined | teid(), %% TEID to be used in 
UPF <- Access
-                     teid_upf2acc :: undefined | teid(), %% TEID to be used in 
UPF -> Access
+                     u2c :: undefined | teid_addr(), %% GTP-U params for UPF 
-> Core
+                     c2u :: undefined | teid_addr(), %% GTP-U params for UPF 
<- Core
+                     a2u :: undefined | teid_addr(), %% GTP-U params for UPF 
<- Access
+                     u2a :: undefined | teid_addr(), %% GTP-U params for UPF 
-> Access
                      seid_loc :: undefined | pfcp_peer:pfcp_seid(), %% local 
SEID, chosen by us
                      seid_rem :: undefined | pfcp_peer:pfcp_seid()  %% remote 
SEID, chosen by the UPF
                     }).
@@ -91,24 +96,24 @@

 %% @doc Indicate reception of E-RAB setup request (from core).
 %% @param Pid  PID of an erab_fsm.
-%% @param TEID  TEID indicated by the MME.
-%% @returns TEID to be sent to the eNB;  an error otherwise.
+%% @param TA  TEID and bind address indicated by the MME.
+%% @returns TEID and Addr to be sent to the eNB;  an error otherwise.
 %% @end
--spec erab_setup_req(pid(), teid()) -> {ok, teid()} |
-                                       {error, term()}.
-erab_setup_req(Pid, TEID) ->
-    gen_statem:call(Pid, {?FUNCTION_NAME, TEID}).
+-spec erab_setup_req(pid(), teid_addr()) -> {ok, teid_addr()} |
+                                            {error, term()}.
+erab_setup_req(Pid, TA) ->
+    gen_statem:call(Pid, {?FUNCTION_NAME, TA}).


 %% @doc Indicate reception of E-RAB setup response (from access).
 %% @param Pid  PID of an erab_fsm.
-%% @param TEID  TEID indicated by the eNB.
-%% @returns TEID to be sent to the MME;  an error otherwise.
+%% @param TA  TEID and bind address indicated by the eNB.
+%% @returns TEID and Addr to be sent to the MME;  an error otherwise.
 %% @end
--spec erab_setup_rsp(pid(), teid()) -> {ok, teid()} |
-                                       {error, term()}.
-erab_setup_rsp(Pid, TEID) ->
-    gen_statem:call(Pid, {?FUNCTION_NAME, TEID}).
+-spec erab_setup_rsp(pid(), teid_addr()) -> {ok, teid_addr()} |
+                                            {error, term()}.
+erab_setup_rsp(Pid, TA) ->
+    gen_statem:call(Pid, {?FUNCTION_NAME, TA}).


 -spec erab_release_req(pid()) -> ok.
@@ -148,12 +153,12 @@
     {keep_state, S};

 erab_wait_setup_req({call, From},
-                    {erab_setup_req, TEID_U2C},
+                    {erab_setup_req, U2C},
                     #erab_state{} = S) ->
-    ?LOG_DEBUG("Rx E-RAB SETUP Req (TEID UPF -> Core ~p)", [TEID_U2C]),
+    ?LOG_DEBUG("Rx E-RAB SETUP Req (U2C ~p)", [U2C]),
     {next_state, session_establish,
      S#erab_state{from = From,
-                  teid_upf2core = TEID_U2C}};
+                  u2c = U2C}};

 erab_wait_setup_req(Event, EventData, S) ->
     ?LOG_ERROR("Unexpected event ~p: ~p", [Event, EventData]),
@@ -182,15 +187,16 @@
               seid = SEID_Rsp, %% matches F-SEID we sent in the ESTABLISH Req
               ie = #{pfcp_cause := 'Request accepted',
                      f_seid := #f_seid{seid = F_SEID},
-                     created_pdr := [#{f_teid := #f_teid{teid = TEID_C2U}},
-                                     #{f_teid := #f_teid{teid = TEID_A2U}}]}} 
->
-            ?LOG_DEBUG("PFCP session established"),
+                     created_pdr := [#{f_teid := F_TEID_C2U},
+                                     #{f_teid := F_TEID_A2U}]}} ->
+            C2U = {F_TEID_C2U#f_teid.teid, f_teid_addr(F_TEID_C2U)},
+            A2U = {F_TEID_A2U#f_teid.teid, f_teid_addr(F_TEID_A2U)},
+            ?LOG_DEBUG("PFCP session established (C2U ~p, A2U ~p)", [C2U, 
A2U]),
             {next_state, erab_wait_setup_rsp,
              S#erab_state{from = undefined,
                           seid_rem = F_SEID, %% SEID to be used in further 
requests from us
-                          teid_core2upf = TEID_C2U,
-                          teid_acc2upf = TEID_A2U},
-             [{reply, From, {ok, TEID_A2U}}]};
+                          c2u = C2U, a2u = A2U},
+             [{reply, From, {ok, A2U}}]};
         _ ->
             ?LOG_ERROR("Rx unexpected PFCP PDU: ~p", [PDU]),
             {stop_and_reply,
@@ -213,12 +219,12 @@
     {stop, {shutdown, timeout}};

 erab_wait_setup_rsp({call, From},
-                    {erab_setup_rsp, TEID_U2A},
+                    {erab_setup_rsp, U2A},
                     #erab_state{} = S) ->
-    ?LOG_DEBUG("Rx E-RAB SETUP Rsp (TEID UPF -> Access ~p)", [TEID_U2A]),
+    ?LOG_DEBUG("Rx E-RAB SETUP Rsp (U2A ~p)", [U2A]),
     {next_state, session_modify,
      S#erab_state{from = From,
-                  teid_upf2acc = TEID_U2A}};
+                  u2a = U2A}};

 %% Catch-all handler for this state
 erab_wait_setup_rsp(Event, EventData, S) ->
@@ -243,7 +249,7 @@
 session_modify(info, #pfcp{} = PDU,
                #erab_state{from = From,
                            seid_loc = SEID_Rsp,
-                           teid_core2upf = TEID_C2U} = S) ->
+                           c2u = C2U} = S) ->
     case PDU of
         #pfcp{type = session_modification_response,
               seid = SEID_Rsp, %% matches F-SEID we sent in the ESTABLISH Req
@@ -251,7 +257,7 @@
             ?LOG_DEBUG("PFCP session modified"),
             {next_state, erab_setup,
              S#erab_state{from = undefined},
-             [{reply, From, {ok, TEID_C2U}}]};
+             [{reply, From, {ok, C2U}}]};
         _ ->
             ?LOG_ERROR("Rx unexpected PFCP PDU: ~p", [PDU]),
             {stop_and_reply,
@@ -371,7 +377,7 @@

 -spec session_establish_req(erab_state()) -> pfcp_peer:pfcp_session_rsp().
 session_establish_req(#erab_state{seid_loc = F_SEID, %% used as F-SEID
-                                  teid_upf2core = TEID_U2C}) ->
+                                  u2c = U2C}) ->
     %% Packet Detection Rules
     OHR = #outer_header_removal{header = 'GTP-U/UDP/IPv4'},
     PDRs = [#{pdr_id => {pdr_id, 1}, %% -- for Core -> Access
@@ -389,11 +395,6 @@
                                          ipv4 = choose},
                        source_interface => {source_interface, 'Access'}}}],
     %% Forwarding Action Rules
-    OHC = #outer_header_creation{n6 = false,
-                                 n19 = false,
-                                 type = 'GTP-U',
-                                 teid = TEID_U2C,
-                                 ipv4 = <<127,0,0,1>>}, %% XXX: Core facing 
addr of the UPF
     FARs = [#{far_id => {far_id, 1}, %% -- for Core -> Access
               %% We don't know the Access side TEID / GTP-U address yet, so we 
set
               %% this FAR to DROP and modify it when we get E-RAB SETUP 
RESPONSE.
@@ -401,27 +402,44 @@
             #{far_id => {far_id, 2}, %% -- for Access -> Core
               apply_action => #{'FORW' => []},
               forwarding_parameters =>
-                #{outer_header_creation => OHC,
+                #{outer_header_creation => ohc(U2C),
                   destination_interface => {destination_interface, 'Core'}}}],
     pfcp_peer:session_establish_req(F_SEID, PDRs, FARs).


 -spec session_modify_req(erab_state()) -> pfcp_peer:pfcp_session_rsp().
 session_modify_req(#erab_state{seid_rem = SEID, %% SEID allocated to us
-                               teid_upf2acc = TEID_U2A}) ->
+                               u2a = U2A}) ->
     %% Forwarding Action Rules
-    OHC = #outer_header_creation{n6 = false,
-                                 n19 = false,
-                                 type = 'GTP-U',
-                                 teid = TEID_U2A,
-                                 ipv4 = <<127,0,0,1>>}, %% XXX: Access facing 
addr of the UPF
     FARs = [#{far_id => {far_id, 1}, %% -- for Core -> Access
               %% Now we know the Core side TEID / GTP-U address, so we modify
               %% this FAR (which was previously set to DROP) to FORW.
               apply_action => #{'FORW' => []},
               forwarding_parameters =>
-                #{outer_header_creation => OHC,
+                #{outer_header_creation => ohc(U2A),
                   destination_interface => {destination_interface, 
'Access'}}}],
     pfcp_peer:session_modify_req(SEID, [], FARs).

+
+ohc({TEID, Addr}) ->
+    OHC = #outer_header_creation{n6 = false,
+                                 n19 = false,
+                                 type = 'GTP-U',
+                                 teid = TEID},
+    case Addr of
+        << _:32 >> ->
+            OHC#outer_header_creation{ipv4 = Addr};
+        << _:128 >> ->
+            OHC#outer_header_creation{ipv6 = Addr}
+    end.
+
+
+%% select an address from F-SEID (prefer IPv6 over IPv4)
+f_teid_addr(#f_teid{ipv6 = IPv6}) when is_binary(IPv6) ->
+    IPv6;
+f_teid_addr(#f_teid{ipv4 = IPv4}) when is_binary(IPv4) ->
+    IPv4;
+f_teid_addr(#f_teid{}) ->
+    undefined. %% TODO: erlang:error()?
+
 %% vim:set ts=4 sw=4 et:
diff --git a/test/erab_fsm_test.erl b/test/erab_fsm_test.erl
index 5c42f61..1722b3c 100644
--- a/test/erab_fsm_test.erl
+++ b/test/erab_fsm_test.erl
@@ -3,6 +3,11 @@
 -include_lib("eunit/include/eunit.hrl").
 -include("pfcp_mock.hrl").

+-define(U2C, {?TEID_U2C, ?ADDR_U2C}).
+-define(C2U, {?TEID_C2U, ?ADDR_C2U}).
+-define(A2U, {?TEID_A2U, ?ADDR_A2U}).
+-define(U2A, {?TEID_U2A, ?ADDR_U2A}).
+
 %% ------------------------------------------------------------------
 %% setup functions
 %% ------------------------------------------------------------------
@@ -57,8 +62,8 @@
 %% ------------------------------------------------------------------

 test_erab_setup_success(Pid) ->
-    [?_assertEqual({ok, ?TEID_A2U}, erab_fsm:erab_setup_req(Pid, ?TEID_U2C)),
-     ?_assertEqual({ok, ?TEID_C2U}, erab_fsm:erab_setup_rsp(Pid, ?TEID_U2A)),
+    [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)),
+     ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)),
      ?_assertEqual(ok, erab_fsm:shutdown(Pid)),
      ?_assertNot(erlang:is_process_alive(Pid))].

@@ -71,7 +76,7 @@
     pfcp_mock:mock_req(session_establish_req, PDU),
     unlink(Pid), %% we expect the FSM to terminate abnormally
     Error = {unexp_pdu, session_establish},
-    [?_assertEqual({error, Error}, erab_fsm:erab_setup_req(Pid, ?TEID_U2C)),
+    [?_assertEqual({error, Error}, erab_fsm:erab_setup_req(Pid, ?U2C)),
      ?_assertNot(erlang:is_process_alive(Pid))].


@@ -81,14 +86,14 @@
     pfcp_mock:mock_req(session_modify_req, PDU),
     unlink(Pid), %% we expect the FSM to terminate abnormally
     Error = {unexp_pdu, session_modify},
-    [?_assertEqual({ok, ?TEID_A2U}, erab_fsm:erab_setup_req(Pid, ?TEID_U2C)),
-     ?_assertEqual({error, Error}, erab_fsm:erab_setup_rsp(Pid, ?TEID_U2A)),
+    [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)),
+     ?_assertEqual({error, Error}, erab_fsm:erab_setup_rsp(Pid, ?U2A)),
      ?_assertNot(erlang:is_process_alive(Pid))].


 test_erab_release_success(Pid) ->
-    [?_assertEqual({ok, ?TEID_A2U}, erab_fsm:erab_setup_req(Pid, ?TEID_U2C)),
-     ?_assertEqual({ok, ?TEID_C2U}, erab_fsm:erab_setup_rsp(Pid, ?TEID_U2A)),
+    [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)),
+     ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)),
      ?_assertEqual(ok, erab_fsm:erab_release_req(Pid)),
      ?_assertEqual(ok, erab_fsm:erab_release_rsp(Pid)),
      ?_assertNot(erlang:is_process_alive(Pid))].
@@ -100,8 +105,8 @@
     pfcp_mock:mock_req(session_delete_req, PDU),
     unlink(Pid), %% we expect the FSM to terminate abnormally
     Error = {unexp_pdu, session_delete},
-    [?_assertEqual({ok, ?TEID_A2U}, erab_fsm:erab_setup_req(Pid, ?TEID_U2C)),
-     ?_assertEqual({ok, ?TEID_C2U}, erab_fsm:erab_setup_rsp(Pid, ?TEID_U2A)),
+    [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)),
+     ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)),
      ?_assertEqual({error, Error}, erab_fsm:erab_release_req(Pid)),
      ?_assertNot(erlang:is_process_alive(Pid))].

@@ -114,8 +119,8 @@


 test_erab_shutdown_session_del(Pid) ->
-    [?_assertEqual({ok, ?TEID_A2U}, erab_fsm:erab_setup_req(Pid, ?TEID_U2C)),
-     ?_assertEqual({ok, ?TEID_C2U}, erab_fsm:erab_setup_rsp(Pid, ?TEID_U2A)),
+    [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)),
+     ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)),
      ?_assertEqual(ok, erab_fsm:shutdown(Pid)),
      ?_assertNot(erlang:is_process_alive(Pid))].

diff --git a/test/pfcp_mock.erl b/test/pfcp_mock.erl
index 635223a..0df8c0b 100644
--- a/test/pfcp_mock.erl
+++ b/test/pfcp_mock.erl
@@ -89,8 +89,10 @@
 pdu_session_establish_rsp() ->
     IEs = #{pfcp_cause => 'Request accepted',
             f_seid => #f_seid{seid = ?SEID_Rem},
-            created_pdr => [#{f_teid => #f_teid{teid = ?TEID_C2U}},
-                            #{f_teid => #f_teid{teid = ?TEID_A2U}}]},
+            created_pdr => [#{f_teid => #f_teid{teid = ?TEID_C2U,
+                                                ipv4 = ?ADDR_C2U}},
+                            #{f_teid => #f_teid{teid = ?TEID_A2U,
+                                                ipv4 = ?ADDR_A2U}}]},
     pdu_rsp(session_establishment_response, ?SEID_Loc, IEs).


diff --git a/test/pfcp_mock.hrl b/test/pfcp_mock.hrl
index 3a54ade..c044939 100644
--- a/test/pfcp_mock.hrl
+++ b/test/pfcp_mock.hrl
@@ -6,4 +6,9 @@
 -define(TEID_A2U,   16#0202). %% UPF <- Access
 -define(TEID_U2A,   16#0002). %% UPF -> Access

+-define(ADDR_U2C,   << 16#7f, 16#00, 16#00, 16#01 >>). %% UPF -> Core
+-define(ADDR_C2U,   << 16#7f, 16#00, 16#01, 16#01 >>). %% UPF <- Core
+-define(ADDR_A2U,   << 16#7f, 16#00, 16#02, 16#02 >>). %% UPF <- Access
+-define(ADDR_U2A,   << 16#7f, 16#00, 16#00, 16#02 >>). %% UPF -> Access
+
 %% vim:set ts=4 sw=4 et:

--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37804?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: Ifdc492c41266d07d0e951dcdcc1e4ba74da0b13b
Gerrit-Change-Number: 37804
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>

Reply via email to