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


Change subject: Create PDP Context in tunnel after rx S6b CreateSessionResp
......................................................................

Create PDP Context in tunnel after rx S6b CreateSessionResp

This refactoring is a preparation to call the gtp_u_kmod APIs.

Change-Id: I911985743af6b3fa90fd78631a562b85ecacce15
---
M src/conv.erl
M src/epdg_gtpc_s2b.erl
M src/epdg_ue_fsm.erl
A src/gtp_u_tun.erl
M src/gtp_utils.erl
5 files changed, 145 insertions(+), 38 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-epdg 
refs/changes/06/35906/1

diff --git a/src/conv.erl b/src/conv.erl
index a041847..95e103d 100644
--- a/src/conv.erl
+++ b/src/conv.erl
@@ -38,7 +38,27 @@
 -include_lib("gtp_utils.hrl").
 -include_lib("conv.hrl").

--export([cause_gtp2gsup/1, gtp2_paa_to_epdg_eua/1, 
epdg_eua_to_gsup_pdp_address/1]).
+-export([ip_to_bin/1, bin_to_ip/1]).
+-export([cause_gtp2gsup/1]).
+-export([gtp2_paa_to_epdg_eua/1, epdg_eua_to_gsup_pdp_address/1]).
+
+% ergw_aaa/src/ergw_aaa_3gpp_dict.erl
+% under GPLv2+
+ip_to_bin(IP) when is_binary(IP) ->
+        IP;
+    ip_to_bin({A, B, C, D}) ->
+        <<A, B, C, D>>;
+    ip_to_bin({A, B, C, D, E, F, G, H}) ->
+        <<A:16, B:16, C:16, D:16, E:16, F:16, G:16, H:16>>.
+
+    bin_to_ip(<<A:8, B:8, C:8, D:8>> = IP) when is_binary(IP) ->
+        {A, B, C, D};
+    bin_to_ip(<<A:16, B:16, C:16, D:16, E:16, F:16, G:16, H:16>> = IP) when 
is_binary(IP) ->
+        {A, B, C, D, E, F, G, H};
+    bin_to_ip({_, _, _, _} = IP) ->
+        IP;
+    bin_to_ip({_, _, _, _, _, _, _, _} = IP) ->
+        IP.

 -spec cause_gtp2gsup(integer()) -> integer().

diff --git a/src/epdg_gtpc_s2b.erl b/src/epdg_gtpc_s2b.erl
index b1c0627..c4ba4dc 100644
--- a/src/epdg_gtpc_s2b.erl
+++ b/src/epdg_gtpc_s2b.erl
@@ -258,6 +258,11 @@
     lager:debug("Add bearer ~p to session ~p~n", [Bearer, Sess]),
     Sess#gtp_session{bearers = sets:add_element(Bearer, 
Sess#gtp_session.bearers)}.

+gtp_session_update_bearer(Sess, OldBearer, NewBearer) ->
+    SetRemoved = sets:del_element(OldBearer, Sess#gtp_session.bearers),
+    SetUpdated = sets:add_element(NewBearer, SetRemoved),
+    Sess#gtp_session{bearers = SetUpdated}.
+
 gtp_session_del_bearer(Sess, Bearer) ->
     lager:debug("Remove bearer ~p from session ~p~n", [Bearer, Sess]),
     Sess1 = Sess#gtp_session{bearers = sets:del_element(Bearer, 
Sess#gtp_session.bearers)},
@@ -269,25 +274,6 @@
 gtp_session_default_bearer(Sess) ->
     gtp_session_find_bearer_by_ebi(Sess, Sess#gtp_session.default_bearer_id).

-
-update_gtp_session_from_create_session_response_ie(none, Sess) ->
-    Sess;
-update_gtp_session_from_create_session_response_ie({_,
-                                                    
#v2_fully_qualified_tunnel_endpoint_identifier{
-                                                        interface_type = 
_Interface,
-                                                        key = TEI, ipv4 = 
_IP4, ipv6 = _IP6},
-                                                    Next}, Sess) ->
-    update_gtp_session_from_create_session_response_ie(maps:next(Next), 
Sess#gtp_session{remote_control_tei = TEI});
-update_gtp_session_from_create_session_response_ie({_, _, Next},
-                                                   Sess) ->
-    update_gtp_session_from_create_session_response_ie(maps:next(Next), Sess).
-
-update_gtp_session_from_create_session_response_ies(#gtp{ie = IEs}, Sess) ->
-    
update_gtp_session_from_create_session_response_ie(maps:next(maps:iterator(IEs)),
 Sess).
-
-update_gtp_session_from_create_session_response(Resp = #gtp{version = v2, type 
= create_session_response}, Sess) ->
-    update_gtp_session_from_create_session_response_ies(#gtp{ie = 
Resp#gtp.ie}, Sess).
-
 % returns Sess if found, undefined it not
 find_gtp_session_by_local_teic(LocalControlTei, State) ->
     {LocalControlTei, Res} = sets:fold(
@@ -313,13 +299,31 @@
             lager:error("Rx unknown TEI ~p: ~p~n", [Resp#gtp.tei, Resp]),
             {noreply, State0};
         Sess0 ->
-            Sess1 = update_gtp_session_from_create_session_response(Resp, 
Sess0),
-            lager:info("s2b: Updated Session after create_session_response: 
~p~n", [Sess1]),
-            State1 = update_gtp_session(Sess0, Sess1, State0),
             % Do GTP specific msg parsing here, pass only relevant fields:
-            #{{v2_pdn_address_allocation,0} := Paa} = Resp#gtp.ie,
+            #{{v2_fully_qualified_tunnel_endpoint_identifier,1} :=
+                #v2_fully_qualified_tunnel_endpoint_identifier{
+                    interface_type = 30, %% "S2b ePDG GTP-C"
+                    key = RemoteTEIC, ipv4 = _IPc4, ipv6 = _IPc6},
+              {v2_pdn_address_allocation,0} := Paa,
+              {v2_bearer_context,0} := #v2_bearer_context{instance = 0, group 
= BearerIE}} = Resp#gtp.ie,
+            % Parse BearerContext:
+            #{{v2_eps_bearer_id,0} := #v2_eps_bearer_id{instance = 0, 
eps_bearer_id = Ebi},
+              {v2_fully_qualified_tunnel_endpoint_identifier,4} :=
+                #v2_fully_qualified_tunnel_endpoint_identifier{
+                    interface_type = 31, %% "S2b-U ePDG GTP-U"
+                    key = RemoteTEID, ipv4 = IPu4, ipv6 = IPu6}
+             } = BearerIE,
+            Bearer = gtp_session_find_bearer_by_ebi(Sess0, Ebi),
+            Sess1 = gtp_session_update_bearer(Sess0, Bearer, 
Bearer#gtp_bearer{remote_data_tei = RemoteTEID}),
+            Sess2 = Sess1#gtp_session{remote_control_tei = RemoteTEIC},
+            lager:info("s2b: Updated Session after create_session_response: 
~p~n", [Sess2]),
+            State1 = update_gtp_session(Sess0, Sess2, State0),
             ResInfo = #{
-                eua => conv:gtp2_paa_to_epdg_eua(Paa)
+                eua => conv:gtp2_paa_to_epdg_eua(Paa),
+                local_teid => Bearer#gtp_bearer.local_data_tei,
+                remote_teid => RemoteTEID,
+                remote_ipv4 => IPu4,
+                remote_ipv6 => IPu6
             },
             
epdg_ue_fsm:received_gtpc_create_session_response(Sess0#gtp_session.pid, {ok, 
ResInfo}),
             {noreply, State1}
@@ -406,7 +410,7 @@
                     instance = 0,
                     interface_type = 31, %% "S2b-U ePDG GTP-U"
                     key = Bearer#gtp_bearer.local_data_tei,
-                    ipv4 = gtp_utils:ip_to_bin(LocalAddr)
+                    ipv4 = conv:ip_to_bin(LocalAddr)
                   }
                 ],
     IEs = [#v2_recovery{restart_counter = RCnt},
@@ -416,7 +420,7 @@
                 instance = Bearer#gtp_bearer.ebi,
                 interface_type = 30, %% "S2b ePDG GTP-C"
                 key = LocalCtlTEI,
-                ipv4 = gtp_utils:ip_to_bin(LocalAddr)
+                ipv4 = conv:ip_to_bin(LocalAddr)
             },
             #v2_access_point_name{instance = 0, apn = [Apn]},
             #v2_selection_mode{mode = 0},
@@ -438,7 +442,7 @@
                instance = Bearer#gtp_bearer.ebi,
                interface_type = 30, %% "S2b ePDG GTP-C"
                key = Bearer#gtp_bearer.local_data_tei,
-               ipv4 = gtp_utils:ip_to_bin(LocalAddr)
+               ipv4 = conv:ip_to_bin(LocalAddr)
            }
     ],
     #gtp{version = v2, type = delete_session_request, tei = RemoteCtlTEI, 
seq_no = SeqNo, ie = IEs}.
@@ -461,7 +465,7 @@
         instance = 0,
         interface_type = 31, %% "S2b-U ePDG GTP-U"
         key = Bearer#gtp_bearer.local_data_tei,
-        ipv4 = gtp_utils:ip_to_bin(LocalAddr)
+        ipv4 = conv:ip_to_bin(LocalAddr)
         }
     ],
     IEs = [#v2_cause{v2_cause = GtpCause},
diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl
index fa780e8..7568db0 100644
--- a/src/epdg_ue_fsm.erl
+++ b/src/epdg_ue_fsm.erl
@@ -244,6 +244,16 @@

 state_authenticated({call, From}, {received_gtpc_create_session_response, 
Result}, Data) ->
         lager:info("ue_fsm state_authenticated 
event=received_gtpc_create_session_response, ~p~n", [Data]),
+        case Result of
+        {ok, ResInfo} ->
+                #{eua := EUA,
+                  local_teid := LocalTEID,
+                  remote_teid := RemoteTEID,
+                  remote_ipv4 := RemoteIPv4 % TODO: remote_ipv6
+                 } = ResInfo,
+                gtp_u_tun:create_pdp_context(RemoteIPv4, EUA, LocalTEID, 
RemoteTEID);
+        _ -> ok
+        end,
         gsup_server:tunnel_response(Data#ue_fsm_data.imsi, Result),
         {keep_state, Data, [{reply,From,ok}]};

diff --git a/src/gtp_u_tun.erl b/src/gtp_u_tun.erl
new file mode 100644
index 0000000..e08b804
--- /dev/null
+++ b/src/gtp_u_tun.erl
@@ -0,0 +1,70 @@
+% GTP-U tun related functionalities
+%
+% (C) 2024 by sysmocom - s.f.m.c. GmbH <[email protected]>
+% Author: Pau Espin Pedrol <[email protected]>
+%
+% All Rights Reserved
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU Affero General Public License as
+% published by the Free Software Foundation; either version 3 of the
+% License, or (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU Affero General Public License
+% along with this program.  If not, see <http://www.gnu.org/licenses/>.
+%
+% Additional Permission under GNU AGPL version 3 section 7:
+%
+% If you modify this Program, or any covered work, by linking or
+% combining it with runtime libraries of Erlang/OTP as released by
+% Ericsson on http://www.erlang.org (or a modified version of these
+% libraries), containing parts covered by the terms of the Erlang Public
+% License (http://www.erlang.org/EPLICENSE), the licensors of this
+% Program grant you additional permission to convey the resulting work
+% without the need to license the runtime libraries of Erlang/OTP under
+% the GNU Affero General Public License. Corresponding Source for a
+% non-source form of such a combination shall include the source code
+% for the parts of the runtime libraries of Erlang/OTP used as well as
+% that of the covered work.
+
+-module(gtp_u_tun).
+-author('Pau Espin Pedrol <[email protected]>').
+-include("conv.hrl").
+
+-export([create_pdp_context/4]).
+
+%%%%%%%%%%%%%%%%%%%%%%
+%%% Internal API
+%%%%%%%%%%%%%%%%%%%%%%
+
+% Obtain ServerRef of the gtp_u_kmod_port process spawned during startup based 
on
+% gtp_u_kmod config:
+get_env_gtp_u_kmod_server_ref() ->
+        GtpuKmodSockets = application:get_env(gtp_u_kmod, sockets, []),
+        [GtpuKmodSocket | _] = GtpuKmodSockets,
+        {GtpuKmodName, _GtpuKmodSockOpts} = GtpuKmodSocket,
+        GtpuKmodServRef = gtp_u_kmod_port:port_reg_name(GtpuKmodName),
+        GtpuKmodServRef.
+
+
+%%%%%%%%%%%%%%%%%%%%%%
+%%% Internal API
+%%%%%%%%%%%%%%%%%%%%%%
+
+% Create a PDP Context on the GTP tundev
+create_pdp_context(PeerAddr, EUA, LocalTEID, RemoteTEID) ->
+        %SGSNaddr = {127,0,0,1}, % TODO: This should be set to the GTP-U IP 
address provided by the PGW
+        %EUA = {127,0,0,1}, % TODO: This should be set to the EUA IP address 
provided by the PGW
+        %LocalTEID = 1234, % TODO: this should be set to our locally generated 
TEID.
+        %RemoteTEID = 56768, % TODO: this should be set to TEID obtained from 
CreateSessionResponse
+        PeerIP = conv:bin_to_ip(PeerAddr), % TODO: IPv6
+        UEIP = conv:bin_to_ip(EUA#epdg_eua.ipv4), % TODO: IPv6.
+        ok.
+        % TODO: This will be enabled once we depend on the gtp_u_kmod module:
+        %ServRef = get_env_gtp_u_kmod_server_ref(),
+        %gen_server:call(ServRef, {PeerIP, UEIP, LocalTEID, RemoteTEID}).
\ No newline at end of file
diff --git a/src/gtp_utils.erl b/src/gtp_utils.erl
index eb0a23a..6098da2 100644
--- a/src/gtp_utils.erl
+++ b/src/gtp_utils.erl
@@ -35,16 +35,8 @@
 -module(gtp_utils).
 -author('Alexander Couzens <[email protected]>').

--export([ip_to_bin/1, plmn_to_bin/3, enum_v2_cause/1]).
+-export([plmn_to_bin/3, enum_v2_cause/1]).

-% ergw_aaa/src/ergw_aaa_3gpp_dict.erl
-% under GPLv2+
-ip_to_bin(IP) when is_binary(IP) ->
-    IP;
-ip_to_bin({A, B, C, D}) ->
-    <<A, B, C, D>>;
-ip_to_bin({A, B, C, D, E, F, G, H}) ->
-    <<A:16, B:16, C:16, D:16, E:16, F:16, G:16, H:16>>.

 % ergw/apps/ergw/test/*.erl
 % under GPLv2+

--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35906?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: erlang/osmo-epdg
Gerrit-Branch: master
Gerrit-Change-Id: I911985743af6b3fa90fd78631a562b85ecacce15
Gerrit-Change-Number: 35906
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>
Gerrit-MessageType: newchange

Reply via email to