- Notifications
You must be signed in to change notification settings - Fork33
erGW - Erlang implementations of GGSN or P-GW
License
travelping/ergw
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This is a 3GPP GGSN and PDN-GW implemented in Erlang. It strives to eventually support all the functionality as defined by3GPP TS 23.002 Section 4.1.3.1 for the GGSN and Section 4.1.4.2.2 for the PDN-GW.
- IMPLEMENTED FEATURES
- EXPERIMENTAL FEATURES
- USER PLANE
- DIAMETER and RADIUS over Gi/SGi
- POLICY CONTROL
- ONLINE/OFFLINE CHARING
- MISSING FEATURES
- ERLANG Version Support
- DOCKER IMAGES
- BUILDING & RUNNING
Messages:
- GTPv1 Create/Update/Delete PDP Context Request on Gn
- GTPv2 Create/Delete Session Request on S5/S8
From the above the following procedures as defined by 3GPP T 23.060 should work:
- PDP Context Activation/Modification/Deactivation Procedure
- PDP Context Activation/Modification/Deactivation Procedure using S4
- Intersystem Change Procedures (handover 2G/3G/LTE)
- 3GPP TS 23.401:
- Sect. 5.4.2.2, HSS Initiated Subscribed QoS Modification (without PCRF)
- Annex D, Interoperation with Gn/Gp SGSNs procedures (seeCONFIG.md)
Experimental features may change or be removed at any moment. Configuration settingsfor them are not guaranteed to work across versions. CheckCONFIG.md andNEWS.md on version upgrades.
- rate limiting, defaults to 100 requests/second
- metrics, seeMETRICS.md
erGW uses the 3GPP control and user plane separation (CUPS) of EPC nodesarchitecture as layed out in3GPP TS 23.214and3GPP TS 29.244.
The SAE-GW, PGW and GGSN interfaces supports DIAMETER and RADIUS over the Gi/SGi interfaceas specified by 3GPP TS 29.061 Section 16.This support is experimental in this version and not all aspects are functional. For RADIUSonly the Authentication and Authorization is full working, Accounting is experimental andnot fully supported. For DIAMETER NASREQ only the Accounting is working.
SeeRADIUS.md for a list of supported Attrbiutes.
Many thanks toOn Waves for sponsoring the RADIUS Authentication implementation.
Example of configurationRADIUS:
%% ...{ergw_aaa, [ {handlers, [ {ergw_aaa_static, [ {'Node-Id', <<"CHANGE-ME">>},%% <- CHANGE {'NAS-Identifier', <<"CHANGE-ME">>},%% <- CHANGE {'NAS-IP-Address', {127,0,0,3}},%% <- CHANGE {'Acct-Interim-Interval',1800},%% <- CHANGE {'Framed-Protocol','PPP'}, {'Service-Type','Framed-User'} ]}, {ergw_aaa_radius, [ {server, {{127,0,0,4},1813, <<"CHANGE-ME-SECRET">>}%% <- CHANGE IP and SECRET }, {termination_cause_mapping, [ {normal,1}, {administrative,6}, {link_broken,2}, {upf_failure,9}, {remote_failure,9}, {cp_inactivity_timeout,4}, {up_inactivity_timeout,4}, {'ASR',6}, {error,9}, {peer_restart,7} ]} ]} ]}, {services, [ {'Default', [ {handler,'ergw_aaa_static'} ]}, {'RADIUS-Acct', [ {handler,'ergw_aaa_radius'} ]} ]}, {apps, [ {default, [ {session, ['Default']}, {procedures, [ {authenticate, []}, {authorize, []}, {start, ['RADIUS-Acct']}, {interim, ['RADIUS-Acct']}, {stop, ['RADIUS-Acct']} ]} ]} ]}]},%% ...
Example of configurationepc-ocsfunction
ofDIAMETER:
%% ...{ergw_aaa, [%% ... {functions, [ {'epc-ocs', [ {handler,ergw_aaa_diameter}, {'Origin-Host', <<"CHANGE-ME">>},%% <- CHANGE: Origin-Host needs to be resolvable%% to local IP (either through /etc/hosts or DNS) {'Origin-Realm', <<"CHANGE-ME">>},%% <- CHANGE {transports, [ [ {connect_to, <<"aaa://CHANGE-ME;transport=tcp">>},%% <- CHANGE {recbuf,131072},%% <- CHANGE {sndbuf,131072}%% <- CHANGE ] ]} ]} ]},%% ...]},%% ...
Example of configurationergw-pgw-epc-rffunction
ofDIAMETER:
%% ...{ergw_aaa, [%% ... {functions, [ {'ergw-pgw-epc-rf', [ {handler,ergw_aaa_diameter}, {'Origin-Host', <<"CHANGE-ME">>},%% <- CHANGE {'Origin-Realm', <<"CHANGE-ME">>},%% <- CHANGE {transports, [ [ {connect_to, <<"aaa://CHANGE-ME;transport=tcp">>},%% <- CHANGE {recbuf,131072},%% <- CHANGE {reuseaddr,false},%% <- CHANGE {sndbuf,131072}%% <- CHANGE ] ]} ]}, ]}, {handlers, [%% ... {ergw_aaa_rf, [ {function,'ergw-pgw-epc-rf'}, {'Destination-Realm', <<"CHANGE-ME">>}%% <- CHANGE ]}, {termination_cause_mapping, [ {normal,1}, {administrative,4}, {link_broken,5}, {upf_failure,5}, {remote_failure,1}, {cp_inactivity_timeout,4}, {up_inactivity_timeout,4}, {'ASR',6}, {error,9}, {peer_restart,1} ]}%% ... ]}, {services, [%% ... {'Rf', [{handler,'ergw_aaa_rf'}]},%% ... ]}, {apps, [ {default, [%% ... {procedures, [%% ... { {rf,'Initial'}, ['Rf']}, { {rf,'Update'}, ['Rf']}, { {rf,'Terminate'}, ['Rf']},%% ... ]} ]}%% ... ]}]},%% ...
DIAMETER is Gx is supported as experimental feature. Only Credit-Control-Request/Answer(CCR/CCA) and Abort-Session-Request/Answer (ASR/ASA) procedures are supported.Re-Auth-Request/Re-Auth-Answer (RAR/RAA) procedures are not supported.
Online charging through Gy is in beta quality with the following known caveats:
- When multiple rating groups are in use, CCR Update requests will contain unitreservation requests for all rating groups, however they should only contain the entriesfor the rating groups where new quotas, threshold and validity's are needed.
Offline charging through Rf is supported in beta quality in this version and works only in"independent online and offline charging" mode (tight interworking of online and offlinecharging is not supported).
Like on Gx only CCR/CCR and ASR/ASA procredures are supported.
The following procedures are assumed/known to beNOT working:
- Secondary PDP Context Activation Procedure
- Secondary PDP Context Activation Procedure using S4
Other shortcomings:
- QoS parameters are hard-coded
All minor version of the current major release and the highest minor version ofthe previous major release will be supported.Due to a bug in OTP 22.x, thenetdev
configuration option oferGW is broken(see). If you need this feature, youmust use OTP 23.x.
When in doubt check theotp_release
section in.github/workflows/main.yml for testedversions.
Docker images are build byGitHub Actions and pushed tohub.docker.com,and by gitlab.com and pushed toquay.io.
erGW Docker image can be get fromquay.io. For create a new image based onergw-c-node
fromquay.io
need run second command:
$ docker run -t -i --rm quay.io/travelping/ergw-c-node:2.4.2 -- /bin/sh/# cd opt/opt# lsergw-c-node
- Erlang OTP23.2.7 is the recommended version.
- Rebar3AnerGW installation needs a user plane provider to handle the GTP-U path. Thisinstance can be installed on the same or different host.
A suitable user plane node based onVPP can be found atVPP-UFP.
erGW can be started withrebar3 command line tools, and build with run can looks like:
$ git clone https://github.com/travelping/ergw.git$cd ergw$ wget https://s3.amazonaws.com/rebar3/rebar3$ chmod u+x ./rebar3$ touch ergw.config
Then fill just createdergw.config file with content like described below providing a suitable configuration, e.g.:
%-*-Erlang-*-[{setup, [{data_dir,"/var/lib/ergw"}, {log_dir,"/var/log/ergw-c-node"} ]}, {kernel, [{logger, [{handler,default,logger_std_h, #{level=>info,config=> #{sync_mode_qlen=>10000,drop_mode_qlen=>10000,flush_qlen=>10000} } } ]} ]}, {ergw, [{'$setup_vars', [{"ORIGIN", {value,"epc.mnc001.mcc001.3gppnetwork.org"}}]}, {plmn_id, {<<"001">>, <<"01">>}}, {http_api, [{port,8080}, {ip, {0,0,0,0}} ]}, {node_id, <<"pgw.$ORIGIN">>}, {sockets, [{cp, [{type,'gtp-u'}, {vrf,cp}, {ip, {127,0,0,1}},freebind, {reuseaddr,true} ]}, {irx, [{type,'gtp-c'}, {vrf,epc}, {ip, {127,0,0,1}}, {reuseaddr,true} ]}, {sx, [{type,'pfcp'}, {socket,cp}, {ip, {172,21,16,2}} ]} ]}, {vrfs, [{sgi, [{pools, [{{10,106,0,1}, {10,106,255,254},32}, {{16#8001,0,0,0,0,0,0,0}, {16#8001,0,0,16#FFFF,0,0,0,0},64} ]}, {'MS-Primary-DNS-Server', {8,8,8,8}}, {'MS-Secondary-DNS-Server', {8,8,4,4}}, {'MS-Primary-NBNS-Server', {127,0,0,1}}, {'MS-Secondary-NBNS-Server', {127,0,0,1}} ]} ]}, {handlers, [{'h1', [{handler,pgw_s5s8}, {protocol,gn}, {sockets, [irx]}, {node_selection, [default]} ]}, {'h2', [{handler,pgw_s5s8}, {protocol,s5s8}, {sockets, [irx]}, {node_selection, [default]} ]} ]}, {apns, [{[<<"tpip">>, <<"net">>], [{vrf,sgi}]}, {[<<"APN1">>], [{vrf,sgi}]} ]}, {teid, {3,6}},% {teid, {Prefix, Length}} - optional, default: {0, 0} {metrics, [ {gtp_path_rtt_millisecond_intervals, [10,100]}% optional, default: [10, 30, 50, 75, 100, 1000, 2000] ]}, {node_selection, [{default, {static, [%% APN NAPTR alternative {"_default.apn.$ORIGIN", {300,64536}, [{"x-3gpp-upf","x-sxb"}],"topon.sx.prox01.$ORIGIN"},%% A/AAAA record alternatives {"topon.sx.prox01.$ORIGIN", [{127,0,0,1}], []} ] } } ] }, {nodes, [{default, [{vrfs, [{cp, [{features, ['CP-Function']}]}, {epc, [{features, ['Access']}]}, {sgi, [{features, ['SGi-LAN']}]}] }, {heartbeat, [ {interval,5000}, {timeout,500}, {retry,5} ]}, {request, [{timeout,30000}, {retry,5}]}] }] }, {path_management, [ {t3,10000}, {n3,5}, {echo,60000}, {idle_timeout,1800000}, {idle_echo,600000}, {down_timeout,3600000}, {down_echo,600000}, {icmp_error_handling,immediate}% optional, can be 'ignore' | 'immediate', by default: immediate ]} ]}, {ergw_aaa, [{handlers, [{ergw_aaa_static, [{'NAS-Identifier', <<"NAS-Identifier">>}, {'Acct-Interim-Interval',600}, {'Framed-Protocol','PPP'}, {'Service-Type','Framed-User'}, {'Node-Id', <<"PGW-001">>}, {'Charging-Rule-Base-Name', <<"cr-01">>}, {rules, #{'Default'=> #{'Rating-Group'=> [3000],'Flow-Information'=> [#{'Flow-Description'=> [<<"permit out ip from any to assigned">>],'Flow-Direction'=> [1]%% DownLink }, #{'Flow-Description'=> [<<"permit out ip from any to assigned">>],'Flow-Direction'=> [2]%% UpLink }],'Metering-Method'=> [1],'Precedence'=> [100] } } } ]} ]}, {services, [{'Default', [{handler,'ergw_aaa_static'}]} ]}, {apps, [{default, [{session, ['Default']}, {procedures, [{authenticate, []}, {authorize, []}, {start, []}, {interim, []}, {stop, []} ]} ]} ]} ]}, {jobs, [{samplers, [{cpu_feedback,jobs_sampler_cpu, []} ]}, {queues, [{path_restart, [{regulators, [{counter, [{limit,100}]}]}, {modifiers, [{cpu_feedback,10}]}%% 10 = % increment by which to modify the limit ]}, {create, [{max_time,5000},%% max 5 seconds {regulators, [{rate, [{limit,100}]}]}, {modifiers, [{cpu_feedback,10}]}%% 10 = % increment by which to modify the limit ]}, {delete, [{regulators, [{counter, [{limit,100}]}]}, {modifiers, [{cpu_feedback,10}]}%% 10 = % increment by which to modify the limit ]}, {other, [{max_time,10000},%% max 10 seconds {regulators, [{rate, [{limit,1000}]}]}, {modifiers, [{cpu_feedback,10}]}%% 10 = % increment by which to modify the limit ]} ]} ]}].
$ ./rebar3 compile$ sudo ./rebar3 shell --setcookie secret --sname ergw --config ergw.config --apps ergw===> Verifying dependencies...CONFIG: enabling persistent_term support===> Analyzing applications...===> Compiling ergwErlang/OTP 23 [erts-11.0.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]Eshell V11.0.3 (abort with ^G)(ergw@localhost)1>application:info().
The configuration is documented inCONFIG.md
Unit test can be run local with:
$ rebar ct
In order to run the IPv6 a number of locap IPv6 addresses have to be added to the host.Check.github/workflows/main.yml or.gitlab-ci.yml the list.
The DNS resolver tests can be run with a local DNS server. The docker image use withthe CI test can also be use for that.
Run it with:
docker run -d --rm \ --name=bind9 \ --publish 127.0.10.1:53:53/udp \ --publish 127.0.10.1:53:53/tcp \ --publish 127.0.10.1:953:953/tcp \ quay.io/travelping/ergw-dns-test-server:latest
and
export CI_DNS_SERVER=127.0.10.1
before running the unit tests.
About
erGW - Erlang implementations of GGSN or P-GW