Skip to content
Snippets Groups Projects
Commit 2ed8c13c authored by Sebastien Merle's avatar Sebastien Merle
Browse files

Add basic PCE server and virtual testbed setup

parent 736709bd
No related branches found
No related tags found
No related merge requests found
Showing
with 1222 additions and 10 deletions
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
set -e
######################################################################################################################## ########################################################################################################################
# Read deployment settings # Read deployment settings
...@@ -54,7 +55,7 @@ TMP_LOGS_FOLDER="$TMP_FOLDER/logs" ...@@ -54,7 +55,7 @@ TMP_LOGS_FOLDER="$TMP_FOLDER/logs"
mkdir -p $TMP_LOGS_FOLDER mkdir -p $TMP_LOGS_FOLDER
echo "Deleting and Creating a new namespace..." echo "Deleting and Creating a new namespace..."
kubectl delete namespace $TFS_K8S_NAMESPACE kubectl delete --ignore-not-found=true namespace $TFS_K8S_NAMESPACE
kubectl create namespace $TFS_K8S_NAMESPACE kubectl create namespace $TFS_K8S_NAMESPACE
printf "\n" printf "\n"
......
...@@ -73,3 +73,7 @@ spec: ...@@ -73,3 +73,7 @@ spec:
protocol: TCP protocol: TCP
port: 11010 port: 11010
targetPort: 11010 targetPort: 11010
- name: pcep
protocol: TCP
port: 4189
targetPort: 4189
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
# Build stage 0 # Build stage 0
FROM erlang:24.3-alpine FROM erlang:24.3-alpine
RUN apk add --no-cache bash RUN apk add --no-cache bash git
RUN mkdir /var/teraflow RUN mkdir /var/teraflow
WORKDIR /var/teraflow WORKDIR /var/teraflow
...@@ -42,6 +42,7 @@ COPY --from=0 /var/teraflow/src/te/_build/prod/rel/tfte /tfte ...@@ -42,6 +42,7 @@ COPY --from=0 /var/teraflow/src/te/_build/prod/rel/tfte /tfte
# Expose relevant ports # Expose relevant ports
EXPOSE 11010 EXPOSE 11010
EXPOSE 4189
ARG ERLANG_LOGGER_LEVEL_DEFAULT=debug ARG ERLANG_LOGGER_LEVEL_DEFAULT=debug
ARG ERLANG_COOKIE_DEFAULT=tfte-unsafe-cookie ARG ERLANG_COOKIE_DEFAULT=tfte-unsafe-cookie
......
{application, epce,
[{description, "An Erlang PCE"},
{vsn, "0.1.0"},
{registered, []},
{mod, {epce_app, []}},
{applications,
[kernel,
stdlib,
pcep_server
]},
{env,[]},
{modules, []},
{licenses, ["Apache 2.0"]},
{links, []}
]}.
-module(epce_app).
-behaviour(application).
%%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Behaviour application functions
-export([start/2, stop/1]).
%%% BEHAVIOUR application FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
start(_StartType, _StartArgs) ->
epce_sup:start_link().
stop(_State) ->
ok.
-module(epce_pcep_server_handler).
-behaviour(gen_pcep_handler).
%%% INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-include_lib("kernel/include/logger.hrl").
-include_lib("pcep_codec/include/pcep_codec_te.hrl").
%%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% API functions
% Behaviour gen_pcep_handler functions
-export([init/1]).
-export([opened/4]).
-export([flow_added/2]).
-export([ready/1]).
-export([request_route/2]).
-export([flow_delegated/2]).
-export([flow_status_changed/3]).
-export([terminate/2]).
%%% RECORDS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-record(state, {}).
%%% API FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% BEHAVIOUR gen_pcep_handler FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init([]) ->
{ok, #{}, #state{}}.
opened(Id, Caps, Sess, State) ->
case epce_server:session_opened(Id, Caps, Sess) of
ok -> {ok, State};
{error, Reason} -> {error, Reason}
end.
flow_added(Flow, State) ->
case epce_server:flow_added(Flow) of
{error, _Reason} = Error -> Error;
ok -> {ok, State}
end.
ready(State) ->
{ok, State}.
request_route(RouteReq, State) ->
case epce_server:request_route(RouteReq) of
{error, _Reason} = Error -> Error;
{ok, Route} -> {ok, Route, State}
end.
flow_delegated(_Flow, State) ->
{ok, State}.
flow_status_changed(FlowId, NewStatus, State) ->
epce_server:flow_status_changed(FlowId, NewStatus),
{ok, State}.
terminate(_Reason, _State) ->
ok.
-module(epce_server).
-behaviour(gen_server).
%%% INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-include_lib("kernel/include/logger.hrl").
-include_lib("pcep_server/include/pcep_server.hrl").
%%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% API Functions
-export([start_link/0]).
-export([get_flows/0]).
-export([update_flow/2]).
% Handler Functions
-export([session_opened/3]).
-export([flow_added/1]).
-export([request_route/1]).
-export([flow_status_changed/2]).
% Behaviour gen_server functions
-export([init/1]).
-export([handle_call/3]).
-export([handle_cast/2]).
-export([handle_continue/2]).
-export([handle_info/2]).
-export([code_change/3]).
-export([terminate/2]).
%%% RECORDS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-record(sess, {
id,
caps,
monref,
pid
}).
-record(state, {
bouncer,
sessions = #{},
sess_pids = #{},
flows = #{}
}).
%%% API FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
get_flows() ->
gen_server:call(?MODULE, get_flows).
update_flow(FlowId, LabelStack) ->
gen_server:call(?MODULE, {update_flow, FlowId, LabelStack}).
%%% HANDLER FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
session_opened(Id, Caps, Pid) ->
gen_server:call(?MODULE, {session_opened, Id, Caps, Pid}).
flow_added(Flow) ->
gen_server:call(?MODULE, {flow_added, Flow}).
request_route(RouteReq) ->
gen_server:call(?MODULE, {request_route, RouteReq}).
flow_status_changed(FlowId, NewStatus) ->
gen_server:call(?MODULE, {flow_status_changed, FlowId, NewStatus}).
%%% BEHAVIOUR gen_server FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init([]) ->
{ok, bouncer_start(#state{})}.
handle_call(get_flows, _From, #state{flows = Flows} = State) ->
{reply, {ok, Flows}, State};
handle_call({update_flow, FlowId, Labels}, From,
#state{flows = Flows, sessions = SessMap} = State) ->
case maps:find(FlowId, Flows) of
error -> {reply, {error, flow_not_found}, State};
{ok, #{owner := Owner, route := #{} = R}} ->
case maps:find(Owner, SessMap) of
error -> {reply, {error, session_not_found}, State};
{ok, #sess{pid = Pid}} ->
#{source := S, destination := D, constraints := C} = R,
ReqRoute = route_from_labels(S, D, C, Labels),
session_update_flow(State, Pid, FlowId, ReqRoute, From),
{noreply, State}
end
end;
handle_call({session_opened, Id, Caps, Pid}, _From,
#state{sessions = SessMap, sess_pids = SessPids} = State) ->
logger:debug("Session with capabilities ~w open to ~w", [Caps, Id]),
case maps:find(Id, SessMap) of
{ok, _} -> {reply, {error, already_opened}, State};
error ->
MonRef = erlang:monitor(process, Pid),
SessRec = #sess{id = Id, caps = Caps, monref = MonRef, pid = Pid},
{reply, ok, State#state{
sessions = SessMap#{Id => SessRec},
sess_pids = SessPids#{Pid => SessRec}
}}
end;
handle_call({flow_added, #{id := Id, route := Route} = Flow},
_From, #state{flows = Flows} = State) ->
logger:debug("Flow ~w with route ~w added", [Id, route_to_labels(Route)]),
{reply, ok, State#state{flows = Flows#{Id => Flow}}};
handle_call({request_route, RouteReq}, _From, State) ->
logger:info("Route from ~w to ~w requested",
[maps:get(source, RouteReq), maps:get(destination, RouteReq)]),
#{source := S, destination := D, constraints := C} = RouteReq,
case compute_path(S, D) of
{error, _Reason} = Error ->
{reply, Error, State};
{ok, Labels} ->
Route = route_from_labels(S, D, C, Labels),
{reply, {ok, Route}, State}
end;
handle_call({flow_status_changed, FlowId, NewStatus}, _From,
#state{flows = Flows} = State) ->
logger:info("Flow ~w status changed to ~w", [FlowId, NewStatus]),
Flow = maps:get(FlowId, Flows),
{reply, ok, State#state{
flows = maps:put(FlowId, Flow#{status := NewStatus}, Flows)}};
handle_call(Request, _From, State) ->
logger:warning("Unexpected request ~w", [Request]),
{reply, {error, unexpected_call}, State}.
handle_cast(_Request, State) ->
{noreply, State}.
handle_continue(_Continue, State) ->
{noreply, State}.
handle_info({flow_updated, FlowId, NewRoute, From},
#state{flows = Flows} = State) ->
logger:info("Flow ~w updated to ~w", [FlowId, route_to_labels(NewRoute)]),
case maps:find(FlowId, Flows) of
error -> {noreply, State};
{ok, Flow} ->
Flows2 = Flows#{FlowId => Flow#{route => NewRoute}},
gen_server:reply(From, ok),
{noreply, State#state{flows = Flows2}}
end;
handle_info({flow_update_error, FlowId, Reason, From}, State) ->
logger:error("Flow ~w updated error: ~w", [FlowId, Reason]),
gen_server:reply(From, {error, Reason}),
{noreply, State};
handle_info({'DOWN', MonRef, process, Pid, _Reason},
#state{sessions = SessMap, sess_pids = PidMap} = State) ->
case maps:take(Pid, PidMap) of
{#sess{id = Id, monref = MonRef}, PidMap2} ->
SessMap2 = maps:remove(Id, SessMap),
%TODO: Do something about the flows from this session ?
{noreply, State#state{
sessions = SessMap2,
sess_pids = PidMap2
}};
_X ->
{noreply, State}
end;
handle_info(_Info, State) ->
{noreply, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
terminate(_Reason, _State) ->
ok.
%%% INTERNAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
compute_path({1, 1, 1, 1}, {6, 6, 6, 6}) ->
{ok, [16020, 16040, 16060]};
compute_path({6, 6, 6, 6}, {1, 1, 1, 1}) ->
{ok, [16040, 16020, 16010]};
compute_path(_Src, _Dst) ->
{error, nopath}.
route_from_labels(Source, Destination, Constraints, Labels) ->
#{
source => Source,
destination => Destination,
constraints => Constraints,
steps => [
#{
is_loose => false,
nai_type => absent,
sid => #mpls_stack_entry{label = L}
}
|| L <- Labels
]
}.
route_to_labels(#{steps := Steps}) ->
[Sid#mpls_stack_entry.label || #{sid := Sid} <- Steps].
%-- Session Interface Functions ------------------------------------------------
session_update_flow(#state{bouncer = Pid}, SessPid, FlowId, Route, Args) ->
Pid ! {update_flow, SessPid, FlowId, Route, Args}.
bouncer_start(#state{bouncer = undefined} = State) ->
Self = self(),
Pid = erlang:spawn_link(fun() ->
bouncer_bootstrap(Self)
end),
receive bouncer_ready -> ok end,
State#state{bouncer = Pid}.
bouncer_bootstrap(Parent) ->
Parent ! bouncer_ready,
bouncer_loop(Parent).
bouncer_loop(Parent) ->
receive
{update_flow, SessPid, FlowId, ReqRoute, Args} ->
case pcep_server_session:update_flow(SessPid, FlowId, ReqRoute) of
{ok, NewRoute} ->
Parent ! {flow_updated, FlowId, NewRoute, Args},
bouncer_loop(Parent);
{error, Reason} ->
Parent ! {flow_update_error, FlowId, Reason, Args},
bouncer_loop(Parent)
end
end.
-module(epce_sup).
-behaviour(supervisor).
%%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Behaviour supervisor functions
-export([start_link/0]).
-export([init/1]).
%%% MACROS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(SERVER, ?MODULE).
-define(PCE_SERVER, epce_server).
%%% BEHAVIOUR SUPERVISOR FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
init([]) ->
SupFlags = #{
strategy => one_for_all,
intensity => 0,
period => 1
},
ServerSpec = #{
id => ?PCE_SERVER,
start => {?PCE_SERVER, start_link, []},
restart => permanent,
shutdown => brutal_kill
},
{ok, {SupFlags, [ServerSpec]}}.
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
{applications, {applications,
[kernel, [kernel,
stdlib, stdlib,
tfpb tfpb,
epce
]}, ]},
{env,[]}, {env,[]},
{modules, []}, {modules, []},
......
[ [
{tfte, [ {tfte, [
{services, [ {services, [
{te, [{http, "localhost", 11010, []}], #{}}, {te, [{http, "localhost", 11010, []}], #{}}
]}
]},
{pcep_server, [
{handler, {epce_pcep_server_handler, []}}
]}, ]},
{epce, [
]},
{grpcbox, [ {grpcbox, [
{servers, [#{ {servers, [#{
grpc_opts => #{ grpc_opts => #{
......
[ [
{tfte, [ {tfte, [
{services, [ {services, [
{te, [ {te, [
...@@ -25,6 +26,13 @@ ...@@ -25,6 +26,13 @@
]} ]}
]}, ]},
{pcep_server, [
{handler, {epce_pcep_server_handler, []}}
]},
{epce, [
]},
{grpcbox, [ {grpcbox, [
{servers, [#{ {servers, [#{
grpc_opts => #{ grpc_opts => #{
......
{erl_opts, [debug_info]}. {erl_opts, [debug_info]}.
{deps, [grpcbox]}. {deps, [
grpcbox,
{pcep_server, {git, "git@github.com:stritzinger/pcep_server.git", {branch, "master"}}}
]}.
{shell, [ {shell, [
{config, "config/dev.config"}, {config, "config/dev.config"},
{apps, [tfte, tfpb, grpcbox]} {apps, [epce, tfte, tfpb, grpcbox]}
]}. ]}.
{project_app_dirs, ["apps/*", "../../proto/src/erlang"]}. {project_app_dirs, ["apps/*", "../../proto/src/erlang"]}.
{relx, [ {relx, [
{release, {tfte, "1.0.0"}, [tfte, tfpb, grpcbox]}, {release, {tfte, "1.0.0"}, [
runtime_tools,
epce,
grpcbox,
tfpb,
tfte
]},
{vm_args_src, "config/vm.args.src"}, {vm_args_src, "config/vm.args.src"},
{sys_config_src, "config/sys.config.src"}, {sys_config_src, "config/sys.config.src"},
{dev_mode, true}, {dev_mode, true},
......
{"1.2.0", {"1.2.0",
[{<<"acceptor_pool">>,{pkg,<<"acceptor_pool">>,<<"1.0.0">>},1}, [{<<"acceptor_pool">>,{pkg,<<"acceptor_pool">>,<<"1.0.0">>},1},
{<<"chatterbox">>,{pkg,<<"ts_chatterbox">>,<<"0.12.0">>},1}, {<<"chatterbox">>,{pkg,<<"ts_chatterbox">>,<<"0.12.0">>},1},
{<<"codec_sequencer">>,
{git,"git@github.com:stritzinger/codec_sequencer.git",
{ref,"fc8760894f7962ef1497bf6ce4247eb75db9d5ca"}},
2},
{<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},1}, {<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},1},
{<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},1}, {<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},1},
{<<"grpcbox">>,{pkg,<<"grpcbox">>,<<"0.15.0">>},0}, {<<"grpcbox">>,{pkg,<<"grpcbox">>,<<"0.15.0">>},0},
{<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},2}]}. {<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},2},
{<<"pcep_codec">>,
{git,"git@github.com:stritzinger/pcep_codec.git",
{ref,"3d1623fdf0c62d3daf400ac65aaf985f8bd40835"}},
1},
{<<"pcep_server">>,
{git,"git@github.com:stritzinger/pcep_server.git",
{ref,"2cf692e7e5fa2e9ac0fd54e5aa64ffb17f4f1b4a"}},
0},
{<<"ranch">>,{pkg,<<"ranch">>,<<"2.0.0">>},1}]}.
[ [
{pkg_hash,[ {pkg_hash,[
{<<"acceptor_pool">>, <<"43C20D2ACAE35F0C2BCD64F9D2BDE267E459F0F3FD23DAB26485BF518C281B21">>}, {<<"acceptor_pool">>, <<"43C20D2ACAE35F0C2BCD64F9D2BDE267E459F0F3FD23DAB26485BF518C281B21">>},
...@@ -12,12 +25,14 @@ ...@@ -12,12 +25,14 @@
{<<"ctx">>, <<"8FF88B70E6400C4DF90142E7F130625B82086077A45364A78D208ED3ED53C7FE">>}, {<<"ctx">>, <<"8FF88B70E6400C4DF90142E7F130625B82086077A45364A78D208ED3ED53C7FE">>},
{<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>}, {<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>},
{<<"grpcbox">>, <<"97C7126296A091602D372EBF5860A04F7BC795B45B33A984CAD2B8E362774FD8">>}, {<<"grpcbox">>, <<"97C7126296A091602D372EBF5860A04F7BC795B45B33A984CAD2B8E362774FD8">>},
{<<"hpack">>, <<"17670F83FF984AE6CD74B1C456EDDE906D27FF013740EE4D9EFAA4F1BF999633">>}]}, {<<"hpack">>, <<"17670F83FF984AE6CD74B1C456EDDE906D27FF013740EE4D9EFAA4F1BF999633">>},
{<<"ranch">>, <<"FBF3D79661C071543256F9051CAF19D65DAA6DF1CF6824D8F37A49B19A66F703">>}]},
{pkg_hash_ext,[ {pkg_hash_ext,[
{<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>}, {<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>},
{<<"chatterbox">>, <<"6478C161BC60244F41CD5847CC3ACCD26D997883E9F7FACD36FF24533B2FA579">>}, {<<"chatterbox">>, <<"6478C161BC60244F41CD5847CC3ACCD26D997883E9F7FACD36FF24533B2FA579">>},
{<<"ctx">>, <<"A14ED2D1B67723DBEBBE423B28D7615EB0BDCBA6FF28F2D1F1B0A7E1D4AA5FC2">>}, {<<"ctx">>, <<"A14ED2D1B67723DBEBBE423B28D7615EB0BDCBA6FF28F2D1F1B0A7E1D4AA5FC2">>},
{<<"gproc">>, <<"580ADAFA56463B75263EF5A5DF4C86AF321F68694E7786CB057FD805D1E2A7DE">>}, {<<"gproc">>, <<"580ADAFA56463B75263EF5A5DF4C86AF321F68694E7786CB057FD805D1E2A7DE">>},
{<<"grpcbox">>, <<"161ABE9E17E7D1982EFA6488ADEAA13C3E847A07984A6E6B224E553368918647">>}, {<<"grpcbox">>, <<"161ABE9E17E7D1982EFA6488ADEAA13C3E847A07984A6E6B224E553368918647">>},
{<<"hpack">>, <<"06F580167C4B8B8A6429040DF36CC93BBA6D571FAEAEC1B28816523379CBB23A">>}]} {<<"hpack">>, <<"06F580167C4B8B8A6429040DF36CC93BBA6D571FAEAEC1B28816523379CBB23A">>},
{<<"ranch">>, <<"C20A4840C7D6623C19812D3A7C828B2F1BD153EF0F124CB69C54FE51D8A42AE0">>}]}
]. ].
...@@ -10,3 +10,4 @@ commands you might need, configuring the network topology, and executing differe ...@@ -10,3 +10,4 @@ commands you might need, configuring the network topology, and executing differe
- [2.3. OECC/PSC'22 Demo (WORK IN PROGRESS)](./2-3-oeccpsc22.md) - [2.3. OECC/PSC'22 Demo (WORK IN PROGRESS)](./2-3-oeccpsc22.md)
- [2.4. ECOC'22 Demo - Disjoint DC-2-DC L3VPN Service (WORK IN PROGRESS)](./2-4-ecoc22.md) - [2.4. ECOC'22 Demo - Disjoint DC-2-DC L3VPN Service (WORK IN PROGRESS)](./2-4-ecoc22.md)
- [2.5. NFV-SDN'22 Demo (PENDING)](./2-5-nfvsdn22.md) - [2.5. NFV-SDN'22 Demo (PENDING)](./2-5-nfvsdn22.md)
- [2.6. Traffic Engineering Demo (PENDING)](./2-6-te-demo.md)
# Directory used for Netgen's operation.
# Default: "/tmp/netgen"
# netgen_runstatedir:
# Clean exit.
# Default: 'false'
# clean_exit:
# Valgrind parameters.
# Default: "--tool=memcheck"
# valgrind_params: "--tool=memcheck --leak-check=full --trace-children=yes"
# valgrind_params: "--tool=memcheck --leak-check=full"
# valgrind_params: "--tool=memcheck --leak-check=full --show-leak-kinds=all"
# valgrind_params: "--tool=callgrind --dump-instr=yes --collect-jumps=yes"
# Perf directory
# Default: [netgen_runstatedir]/perf
# perf_dir:
# Plugins configuration.
plugins:
frr:
# FRR's sysconfdir (--sysconfdir).
# Default: "/etc/frr"
# sysconfdir:
# FRR's localstatedir (--localstatedir).
# Default: "/var/run/frr"
# localstatedir:
# FRR's user (--enable-user).
# Default: "frr"
# user:
user: "root"
# FRR's group (--enable-group).
# Default: "frr"
# group:
group: "root"
# Directory to store FRR logs.
# Default: [netgen_runstatedir]/frrlogs
# logdir:
tcpdump:
# Directory to store tcpdump captures.
# Default: [netgen_runstatedir]/pcaps
# pcap_dir:
# Filter on which nodes tcpdump should run.
# Default: []
# whitelist:
# Filter on which nodes tcpdump should not run.
# Default: []
# blacklist:
tmux:
# Path of tmux script used to open a shell on all routers.
# Default: [netgen_runstatedir]/tmux.sh
# file:
# Panels per node.
# Default: 1
# panels-per-node:
bird:
# BIRD's sysconfdir (--sysconfdir).
# Default: "/etc/bird"
# sysconfdir:
# BIRD's localstatedir (--localstatedir).
# Default: "/var/run/bird"
# localstatedir:
# BIRD's user (--enable-user).
# Default: "bird"
# user:
# BIRD's group (--enable-group).
# Default: "bird"
# group:
# Directory to store BIRD logs.
# Default: [netgen_runstatedir]/birdlogs
# logdir:
bgpsimple:
# Path to bgp_simple script
# Default: "bgp_simple.pl"
# path:
iou:
# IOU working directory.
# Default: [netgen_runstatedir]/iou
# dir:
dynamips:
# dynamips working directory.
# Default: [netgen_runstatedir]/dynamips
# dir:
#
# +---------+
# | |
# | SRC |
# | 9.9.9.1 |
# | |
# +---------+
# |eth-rt1 (.1)
# |
# |10.0.10.0/24
# |
# |eth-src (.2)
# +---------+ .
# | | .
# | RT1 |eth-rt1-pce (???) .
# | 1.1.1.1 +----------------------------------+
# | 16010 | . ??? |
# +---------+ . |
# |eth-sw1 . |
# | . |
# | . |
# | . |
# +---------+ | +---------+ . |
# | | | | | . |
# | RT2 |eth-sw1 | eth-sw1| RT3 | . |
# | 2.2.2.2 +----------+----------+ 3.3.3.3 | . |
# | 16020 | 10.0.1.0/24 | 16030 | . |
# +---------+ +---------+ .eth-pce-rt1|(???)
# eth-rt4-1| |eth-rt4-2 eth-rt5-1| |eth-rt5-2. +----+----+
# | | | | . | |
# 10.0.2.0/24| |10.0.3.0/24 10.0.4.0/24| |10.0.5.0/24 | PCE |
# | | | | . | ???? |
# eth-rt2-1| |eth-rt2-2 eth-rt3-1| |eth-rt3-2. | |
# +---------+ +---------+ . +----+----+
# | | | | .eth-pce-rt6|(???)
# | RT4 | 10.0.6.0/24 | RT5 | . |
# | 4.4.4.4 +---------------------+ 5.5.5.5 | . |
# | 16040 |eth-rt5 eth-rt4| 16050 | . |
# +---------+ +---------+ . |
# eth-rt6| |eth-rt6 . |
# | | . |
# 10.0.7.0/24| |10.0.8.0/24 |
# | +---------+ | . |
# +----------| |-----------+ . |
# eth-rt4| RT6 |eth-rt5 . |
# | 6.6.6.6 |eth-rt6-pce (????) . ???? |
# | 16060 +----------------------------------+
# +---------+ .
# |eth-dst (.1) .
# | .
# |10.0.11.0/24
# |
# |eth-rt6 (.2)
# +---------+
# | |
# | DST |
# | 9.9.9.2 |
# | |
# +---------+
#
---
routers:
src:
links:
lo:
ipv4: 9.9.9.1/32
ipv6: 2001:db8:1066::1/128
mpls: yes
eth-rt1:
peer: [rt1, eth-src]
ipv4: 10.0.10.1/24
mpls: yes
frr:
zebra:
run: yes
config:
shell: |
ip route add 9.9.9.2/32 encap mpls 1111 via inet 10.0.10.2 src 9.9.9.1
rt1:
links:
lo:
ipv4: 1.1.1.1/32
mpls: yes
eth-sw1:
peer: [sw1, sw1-rt1]
ipv4: 10.0.1.1/24
mpls: yes
eth-src:
peer: [src, eth-rt1]
ipv4: 10.0.10.2/24
mpls: yes
frr:
zebra:
run: yes
config:
pathd:
args: "-M pathd_pcep"
config: |
debug pathd pcep basic
segment-routing
traffic-eng
mpls-te on
policy color 1 endpoint 6.6.6.6
name DEFAULT
binding-sid 1111
candidate-path preference 100 name RUNTIME dynamic
!
!
pcep
pce-config CONFIG
source-address ip 1.1.1.1
pce PCE
address ip ${PCE_IP}
config CONFIG
pcc
peer PCE
!
isisd:
run: yes
config: |
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-sw1
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0001.00
is-type level-1
redistribute ipv4 static level-1
redistribute ipv4 connected level-1
topology ipv6-unicast
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 1.1.1.1/32 index 10 explicit-null
segment-routing prefix 2001:db8:1000::1/128 index 11 explicit-null
!
shell: |
ip route add 9.9.9.1/32 dev eth-src
ip link add eth-rt1-pce type veth peer name eth-pce-rt1
ip addr add ${RT1_PCE_INT_IF_IP}/24 dev eth-rt1-pce
ip link set eth-pce-rt1 netns ${PCE_NETNS}
ip -n ${PCE_NETNS} addr add ${RT1_PCE_EXT_IF_IP}/24 dev eth-pce-rt1
ip link set eth-rt1-pce up
ip -n ${PCE_NETNS} link set eth-pce-rt1 up
ip route add ${RT1_PCE_EXT_IF_IP}/24 via ${RT1_PCE_INT_IF_IP} dev eth-rt1-pce src 1.1.1.1
ip -n ${PCE_NETNS} route add ${RT1_PCE_INT_IF_IP}/32 via ${RT1_PCE_EXT_IF_IP} dev eth-pce-rt1
ip -n ${PCE_NETNS} route add 1.1.1.1/32 via ${RT1_PCE_EXT_IF_IP} dev eth-pce-rt1
rt2:
links:
lo:
ipv4: 2.2.2.2/32
ipv6: 2001:db8:1000::2/128
mpls: yes
eth-sw1:
peer: [sw1, sw1-rt2]
ipv4: 10.0.1.2/24
mpls: yes
eth-rt4-1:
peer: [rt4, eth-rt2-1]
ipv4: 10.0.2.2/24
mpls: yes
eth-rt4-2:
peer: [rt4, eth-rt2-2]
ipv4: 10.0.3.2/24
mpls: yes
frr:
zebra:
run: yes
config:
isisd:
run: yes
config: |
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-sw1
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
interface eth-rt4-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt4-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0002.00
is-type level-1
topology ipv6-unicast
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 2.2.2.2/32 index 20 no-php-flag
segment-routing prefix 2001:db8:1000::2/128 index 21 no-php-flag
!
rt3:
links:
lo:
ipv4: 3.3.3.3/32
ipv6: 2001:db8:1000::3/128
mpls: yes
eth-sw1:
peer: [sw1, sw1-rt3]
ipv4: 10.0.1.3/24
mpls: yes
eth-rt5-1:
peer: [rt5, eth-rt3-1]
ipv4: 10.0.4.3/24
mpls: yes
eth-rt5-2:
peer: [rt5, eth-rt3-2]
ipv4: 10.0.5.3/24
mpls: yes
frr:
zebra:
run: yes
config:
isisd:
run: yes
config: |
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-sw1
ip router isis 1
ipv6 router isis 1
isis hello-multiplier 3
!
interface eth-rt5-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt5-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0003.00
is-type level-1
topology ipv6-unicast
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 3.3.3.3/32 index 30 no-php-flag
segment-routing prefix 2001:db8:1000::3/128 index 31 no-php-flag
!
rt4:
links:
lo:
ipv4: 4.4.4.4/32
ipv6: 2001:db8:1000::4/128
mpls: yes
eth-rt2-1:
peer: [rt2, eth-rt4-1]
ipv4: 10.0.2.4/24
mpls: yes
eth-rt2-2:
peer: [rt2, eth-rt4-2]
ipv4: 10.0.3.4/24
mpls: yes
eth-rt5:
peer: [rt5, eth-rt4]
ipv4: 10.0.6.4/24
mpls: yes
eth-rt6:
peer: [rt6, eth-rt4]
ipv4: 10.0.7.4/24
mpls: yes
frr:
zebra:
run: yes
config:
isisd:
run: yes
config: |
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt2-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt2-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt5
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt6
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0004.00
is-type level-1
topology ipv6-unicast
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 4.4.4.4/32 index 40 no-php-flag
segment-routing prefix 2001:db8:1000::4/128 index 41 no-php-flag
!
rt5:
links:
lo:
ipv4: 5.5.5.5/32
ipv6: 2001:db8:1000::5/128
mpls: yes
eth-rt3-1:
peer: [rt3, eth-rt5-1]
ipv4: 10.0.4.5/24
mpls: yes
eth-rt3-2:
peer: [rt3, eth-rt5-2]
ipv4: 10.0.5.5/24
mpls: yes
eth-rt4:
peer: [rt4, eth-rt5]
ipv4: 10.0.6.5/24
mpls: yes
eth-rt6:
peer: [rt6, eth-rt5]
ipv4: 10.0.8.5/24
mpls: yes
frr:
zebra:
run: yes
config:
isisd:
run: yes
config: |
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt3-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt3-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt4
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt6
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0005.00
is-type level-1
topology ipv6-unicast
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 5.5.5.5/32 index 50 no-php-flag
segment-routing prefix 2001:db8:1000::5/128 index 51 no-php-flag
!
rt6:
links:
lo:
ipv4: 6.6.6.6/32
ipv6: 2001:db8:1000::6/128
mpls: yes
eth-rt4:
peer: [rt4, eth-rt6]
ipv4: 10.0.7.6/24
mpls: yes
eth-rt5:
peer: [rt5, eth-rt6]
ipv4: 10.0.8.6/24
mpls: yes
eth-dst:
peer: [dst, eth-rt6]
ipv4: 10.0.11.1/24
mpls: yes
frr:
zebra:
run: yes
config:
pathd:
args: "-M pathd_pcep"
config: |
debug pathd pcep
segment-routing
traffic-eng
policy color 1 endpoint 1.1.1.1
name DEFAULT
binding-sid 6666
candidate-path preference 200 name RUNTIME dynamic
!
!
pcep
pce-config CONFIG
source-address ip 6.6.6.6
pce PCE
address ip ${PCE_IP}
config CONFIG
pcc
peer PCE
!
isisd:
run: yes
config: |
interface lo
ip router isis 1
ipv6 router isis 1
isis passive
!
interface eth-rt4
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
interface eth-rt5
ip router isis 1
ipv6 router isis 1
isis network point-to-point
isis hello-multiplier 3
!
router isis 1
net 49.0000.0000.0000.0006.00
is-type level-1
redistribute ipv4 static level-1
redistribute ipv4 connected level-1
topology ipv6-unicast
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 6.6.6.6/32 index 60 explicit-null
segment-routing prefix 2001:db8:1000::6/128 index 61 explicit-null
!
shell: |
ip route add 9.9.9.2/32 dev eth-dst
ip link add eth-rt6-pce type veth peer name eth-pce-rt6
ip addr add ${RT6_PCE_INT_IF_IP}/24 dev eth-rt6-pce
ip link set eth-pce-rt6 netns ${PCE_NETNS}
ip -n ${PCE_NETNS} addr add ${RT6_PCE_EXT_IF_IP}/24 dev eth-pce-rt6
ip link set eth-rt6-pce up
ip -n ${PCE_NETNS} link set eth-pce-rt6 up
ip route add ${RT6_PCE_EXT_IF_IP}/24 via ${RT6_PCE_INT_IF_IP} dev eth-rt6-pce src 6.6.6.6
ip -n ${PCE_NETNS} route add ${RT6_PCE_INT_IF_IP}/32 via ${RT6_PCE_EXT_IF_IP} dev eth-pce-rt6
ip -n ${PCE_NETNS} route add 6.6.6.6/32 via ${RT6_PCE_EXT_IF_IP} dev eth-pce-rt6
dst:
links:
lo:
ipv4: 9.9.9.2/32
ipv6: 2001:db8:1066::2/128
mpls: yes
eth-rt6:
peer: [rt6, eth-dst]
ipv4: 10.0.11.2/24
mpls: yes
frr:
zebra:
run: yes
config:
shell: |
ip route add 9.9.9.1/32 encap mpls 6666 via inet 10.0.11.1
switches:
sw1:
links:
sw1-rt1:
peer: [rt1, rt1-sw1]
sw1-rt2:
peer: [rt2, rt2-sw1]
sw1-rt3:
peer: [rt3, rt3-sw1]
frr:
#perf: yes
#valgrind: yes
base-configs:
all: |
hostname %(node)
password 1
log file %(logdir)/%(node)-%(daemon).log
log commands
zebra: |
debug zebra kernel
debug zebra packet
debug zebra mpls
isisd: |
debug isis events
debug isis route-events
debug isis spf-events
debug isis sr-events
debug isis lsp-gen
#!/bin/bash
set -e
ROOTDIR="$( cd $( dirname $0 ); pwd )"
RUNDIR="$( pwd )"
NEGENDIR="${RUNDIR}/netgen"
if [[ ! -f "${NEGENDIR}/exe/netgen" ]]; then
echo "Failed to find Netgen binary at ${NEGENDIR}/exe/netgen"
exit 1
fi
export PCE_NETNS="$1"
export PCE_IP="$2"
RT1_INT_IP="$3"
RT1_EXT_IP="$4"
RT6_INT_IP="$5"
RT6_EXT_IP="$6"
if [[ -z $PCE_NETNS || -z $PCE_IP || -z RT1_INT_IP || -z RT1_EXT_IP || -z RT6_INT_IP || -z RT6_EXT_IP ]]; then
echo "USAGE: $0 PCE_NETNS PCE_IP RT1_INT_IP RT1_EXT_IP RT6_INT_IP RT6_EXT_IP"
echo " e.g: $0 cni-588a2d06-e64f-907b-d51b-bed0307007c9 10.1.103.133 10 11 12 13"
exit 1
fi
IFS=. read PCE_IP1 PCE_IP2 PCE_IP3 PCE_IP4 <<< "$PCE_IP"
export RT1_PCE_INT_IF_IP="$PCE_IP1.$PCE_IP2.$PCE_IP3.$RT1_INT_IP"
export RT1_PCE_EXT_IF_IP="$PCE_IP1.$PCE_IP2.$PCE_IP3.$RT1_EXT_IP"
export RT6_PCE_INT_IF_IP="$PCE_IP1.$PCE_IP2.$PCE_IP3.$RT6_INT_IP"
export RT6_PCE_EXT_IF_IP="$PCE_IP1.$PCE_IP2.$PCE_IP3.$RT6_EXT_IP"
cp "${ROOTDIR}/2-6-netgen-config.yml" "${RUNDIR}/config.yml"
cat "${ROOTDIR}/2-6-netgen-topology.yml.template" | envsubst > "${RUNDIR}/topology.yml"
sudo -i bash -c "\
cd ${RUNDIR}/netgen;\
sysctl -w net.ipv6.conf.all.disable_ipv6=1;\
sysctl -w net.ipv6.conf.default.disable_ipv6=1;\
sysctl -w net.ipv4.conf.all.rp_filter=0;\
PATH=/usr/lib/frr:\$PATH ./exe/netgen ../topology.yml -c ../config.yml"
# 2.6. Traffic Engineering Demo (PENDING)
## Setup Test-Bed
### Setup libyang
$ sudo apt update
$ sudo apt-get install cmake libpcre2-dev git make build-essential
$ mkdir -p ~/testbed
$ cd ~/testbed
$ git clone git@github.com:CESNET/libyang.git
$ cd libyang
$ git checkout v2.0.0
$ mkdir build; cd build
$ cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr -D CMAKE_BUILD_TYPE:String="Release" ..
$ make
$ sudo make install
### Setup Free Range Routing
$ sudo apt update
$ sudo apt-get install git autoconf automake libtool make libreadline-dev texinfo pkg-config libpam0g-dev libjson-c-dev bison flex libc-ares-dev python3-dev python3-sphinx install-info build-essential libsnmp-dev perl libcap-dev python2 libelf-dev libunwind-dev protobuf-c-compiler libprotobuf-c-dev libsystemd-dev
$ mkdir -p ~/testbed
$ cd ~/testbed
$ git clone git@github.com:opensourcerouting/frr.git
$ cd frr
$ curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
$ sudo python2 ./get-pip.py
$ export CFLAGS="-I /usr/local/include -g -O2"
$ sudo rm -rf /usr/lib/frr
$ sudo rm -rf /var/run/frr
$ sudo mkdir -p /etc/frr
$ sudo mkdir -p /var/run/frr
$ sudo chown -R root:root /etc/frr
$ ./bootstrap.sh
$ ./configure \
--prefix=/usr \
--includedir=\${prefix}/include \
--enable-exampledir=\${prefix}/share/doc/frr/examples \
--bindir=\${prefix}/bin \
--sbindir=\${prefix}/lib/frr \
--libdir=\${prefix}/lib/frr \
--libexecdir=\${prefix}/lib/frr \
--localstatedir=/var/run/frr \
--sysconfdir=/etc/frr \
--with-moduledir=\${prefix}/lib/frr/modules \
--enable-configfile-mask=0640 \
--enable-logfile-mask=0640 \
--enable-snmp=agentx \
--enable-multipath=64 \
--enable-user=root \
--enable-group=root \
--enable-vty-group=root \
--enable-vtysh \
--with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion \
--enable-systemd=yes \
--enable-config-rollbacks \
--enable-pathd \
--enable-pcep
$ make
$ sudo make install
### Setup NetGen
$ sudo apt update
$ sudo apt-get install git ruby ruby-dev tmux gettext-base
$ mkdir -p ~/testbed
$ cd ~/testbed
$ git clone git@github.com:sylane/netgen.git
$ cd netgen
$ git checkout teraflow
$ sudo gem install bundler:1.15
$ bundle _1.15_ install
### Run the Test-Bed
To start the testbed, we need to figure out the IP of the TE service:
$ kubectl --namespace tfs get $(kubectl --namespace tfs get pods --selector=app=teservice -o name) --template '{{.status.podIP}}'
And select the network namespace that defines it by looking into each of them until you find the correct one:
$ ip netns list
$ sudo ip -n XXX addr list
When we have the IP and namespace we can start the testbed.
In first console:
$ cd ~/testbed
$ ../tfs-ctrl/tutorial/2-6-te-demo-start-testbed.sh NETWORK_NAMESPACE TE_SERVICE_IP 10 11 12 13
Then in second console:
$ sudo -i
# cd /tmp/negen
# ./tmux.sh
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment