Commit 0fbf935c authored by Sebastien Merle's avatar Sebastien Merle
Browse files

Add support for PCE initiated LSPs

parent b428cc8a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
-export([init/1]).
-export([opened/4]).
-export([flow_added/2]).
-export([flow_initiated/2]).
-export([ready/1]).
-export([request_route/2]).
-export([flow_delegated/2]).
@@ -49,6 +50,10 @@ flow_added(Flow, State) ->
        ok -> {ok, State}
    end.

flow_initiated(Flow, State) ->
    ok = epce_server:flow_initiated(Flow),
    {ok, State}.

ready(State) ->
    {ok, State}.

+74 −9
Original line number Diff line number Diff line
@@ -15,10 +15,12 @@
-export([start_link/0]).
-export([get_flows/0]).
-export([update_flow/2]).
-export([initiate_flow/4]).

% Handler Functions
-export([session_opened/3]).
-export([flow_added/1]).
-export([flow_initiated/1]).
-export([request_route/1]).
-export([flow_status_changed/2]).

@@ -32,6 +34,11 @@
-export([terminate/2]).


%%% MACROS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-define(LARGE_TIMEOUT, 20000).


%%% RECORDS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-record(sess, {
@@ -60,6 +67,10 @@ get_flows() ->
update_flow(FlowId, LabelStack) ->
    gen_server:call(?MODULE, {update_flow, FlowId, LabelStack}).

initiate_flow(Name, FromAddr, ToAddr, BindingLabel) ->
    gen_server:call(?MODULE, {initiate_flow, Name, FromAddr, ToAddr,
                              BindingLabel}, ?LARGE_TIMEOUT).


%%% HANDLER FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

@@ -69,6 +80,9 @@ session_opened(Id, Caps, Pid) ->
flow_added(Flow) ->
    gen_server:call(?MODULE, {flow_added, Flow}).

flow_initiated(Flow) ->
    gen_server:call(?MODULE, {flow_initiated, Flow}).

request_route(RouteReq) ->
    gen_server:call(?MODULE, {request_route, RouteReq}).

@@ -92,11 +106,26 @@ handle_call({update_flow, FlowId, Labels}, From,
                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),
                    ReqRoute = routereq_from_labels(S, D, C, Labels),
                    session_update_flow(State, Pid, FlowId, ReqRoute, From),
                    {noreply, State}
            end
    end;
handle_call({initiate_flow, Name, FromAddr, ToAddr, Binding}, From,
            #state{sessions = SessMap} = State) ->
    case maps:find(FromAddr, SessMap) of
        error -> {reply, {error, session_not_found}, State};
        {ok, #sess{pid = Pid}} ->
            case compute_path(FromAddr, ToAddr) of
                {error, Reason} ->
                    {reply, {error, Reason}, State};
                {ok, Labels} ->
                    InitRoute = routeinit_from_labels(Name, FromAddr, ToAddr,
                                                      [], Binding, Labels),
                    session_initiate_flow(State, Pid, InitRoute, 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]),
@@ -114,6 +143,11 @@ 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({flow_initiated, #{id := Id, route := Route} = Flow},
            _From, #state{flows = Flows} = State) ->
    logger:debug("Flow ~w with route ~p initiated",
                 [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)]),
@@ -122,7 +156,7 @@ handle_call({request_route, RouteReq}, _From, State) ->
        {error, _Reason} = Error ->
            {reply, Error, State};
        {ok, Labels} ->
            Route = route_from_labels(S, D, C, Labels),
            Route = routereq_from_labels(S, D, C, Labels),
            {reply, {ok, Route}, State}
    end;
handle_call({flow_status_changed, FlowId, NewStatus}, _From,
@@ -131,12 +165,13 @@ handle_call({flow_status_changed, FlowId, NewStatus}, _From,
    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]),
handle_call(Request, From, State) ->
    logger:warning("Unexpected call from ~w: ~p", [From, Request]),
    {reply, {error, unexpected_call}, State}.


handle_cast(_Request, State) ->
handle_cast(Request, State) ->
    logger:warning("Unexpected cast: ~p", [Request]),
    {noreply, State}.

handle_continue(_Continue, State) ->
@@ -153,7 +188,17 @@ handle_info({flow_updated, FlowId, NewRoute, From},
            {noreply, State#state{flows = Flows2}}
    end;
handle_info({flow_update_error, FlowId, Reason, From}, State) ->
    logger:error("Flow ~w updated error: ~w", [FlowId, Reason]),
    logger:error("Flow ~w updated error: ~p", [FlowId, Reason]),
    gen_server:reply(From, {error, Reason}),
    {noreply, State};
handle_info({flow_initiated, #{id := FlowId, route := Route} = Flow, From},
            #state{flows = Flows} = State) ->
    logger:info("Flow ~w initiated to ~p",
                [FlowId, route_to_labels(Route)]),
    gen_server:reply(From, {ok, FlowId}),
    {noreply, State#state{flows = Flows#{FlowId => Flow}}};
handle_info({flow_init_error, Reason, From}, State) ->
    logger:error("Flow initialisation error: ~p", [Reason]),
    gen_server:reply(From, {error, Reason}),
    {noreply, State};
handle_info({'DOWN', MonRef, process, Pid, _Reason},
@@ -169,7 +214,8 @@ handle_info({'DOWN', MonRef, process, Pid, _Reason},
        _X ->
            {noreply, State}
    end;
handle_info(_Info, State) ->
handle_info(Info, State) ->
    logger:warning("Unexpected message: ~p", [Info]),
    {noreply, State}.

code_change(_OldVsn, State, _Extra) ->
@@ -189,10 +235,10 @@ compute_path(From, To) ->
            {ok, Labels};
        {error, Reason} ->
            logger:warning("Failed to find a route from ~p to ~p", [From, To]),
            {error, Reason}
            {error, route_not_found}
    end.

route_from_labels(Source, Destination, Constraints, Labels) ->
routereq_from_labels(Source, Destination, Constraints, Labels) ->
    #{
        source => Source,
        destination => Destination,
@@ -207,6 +253,13 @@ route_from_labels(Source, Destination, Constraints, Labels) ->
        ]
    }.

routeinit_from_labels(Name, Source, Destination, Constraints, Binding, Labels) ->
    Route = routereq_from_labels(Source, Destination, Constraints, Labels),
    Route#{
        name => Name,
        binding_label => Binding
    }.

route_to_labels(#{steps := Steps}) ->
    [Sid#mpls_stack_entry.label || #{sid := Sid} <- Steps].

@@ -216,6 +269,9 @@ route_to_labels(#{steps := Steps}) ->
session_update_flow(#state{bouncer = Pid}, SessPid, FlowId, Route, Args) ->
    Pid ! {update_flow, SessPid, FlowId, Route, Args}.

session_initiate_flow(#state{bouncer = Pid}, SessPid, Route, Args) ->
    Pid ! {initiate_flow, SessPid, Route, Args}.

bouncer_start(#state{bouncer = undefined} = State) ->
    Self = self(),
    Pid = erlang:spawn_link(fun() ->
@@ -238,5 +294,14 @@ bouncer_loop(Parent) ->
                {error, Reason} ->
                    Parent ! {flow_update_error, FlowId, Reason, Args},
                    bouncer_loop(Parent)
            end;
        {initiate_flow, SessPid, InitRoute, Args} ->
            case pcep_server_session:initiate_flow(SessPid, InitRoute) of
                {ok, Flow} ->
                    Parent ! {flow_initiated, Flow, Args},
                    bouncer_loop(Parent);
                {error, Reason} ->
                    Parent ! {flow_init_error, Reason, Args},
                    bouncer_loop(Parent)
            end
    end.
+2 −2
Original line number Diff line number Diff line
@@ -11,11 +11,11 @@
 {<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},2},
 {<<"pcep_codec">>,
  {git,"git@github.com:stritzinger/pcep_codec.git",
       {ref,"3d1623fdf0c62d3daf400ac65aaf985f8bd40835"}},
       {ref,"84dcc430b2aa427984c100cc19dd35d946b22ff9"}},
  1},
 {<<"pcep_server">>,
  {git,"git@github.com:stritzinger/pcep_server.git",
       {ref,"2cf692e7e5fa2e9ac0fd54e5aa64ffb17f4f1b4a"}},
       {ref,"3910bf5546879cb91a3483008b6aed11753deaa6"}},
  0},
 {<<"ranch">>,{pkg,<<"ranch">>,<<"2.0.0">>},1}]}.
[
+2 −13
Original line number Diff line number Diff line
@@ -103,17 +103,11 @@ routers:
          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
              pce-initiated
              address ip ${PCE_IP}
              config CONFIG
             pcc
@@ -438,16 +432,11 @@ routers:
          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
              pce-initiated
              address ip ${PCE_IP}
              config CONFIG
             pcc
+0 −2
Original line number Diff line number Diff line
@@ -41,7 +41,5 @@ cat "${ROOTDIR}/2-6-netgen-topology.yml.template" | envsubst > "${RUNDIR}/topolo

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"
Loading