Skip to content

Commit 8dba591

Browse files
author
Szymon Mentel
committed
Set connections between Flow Mods and Flow Tables; refactor
Getting Flow Tables' identifiers is to be implemented .
1 parent 80a850a commit 8dba591

7 files changed

Lines changed: 204 additions & 74 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ rel/dobby_ofclient
1010
rebar
1111
log
1212
logs
13+
Mnesia.*

include/dobby_ofclient.hrl

Lines changed: 0 additions & 6 deletions
This file was deleted.

include/dobby_oflib.hrl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
%%%=============================================================================
2+
%%% @copyright (C) 2015, Erlang Solutions Ltd
3+
%%% @author Szymon Mentel <szymon.mentel@erlang-solutions.com>
4+
%%%=============================================================================
5+
%% Add includes and records
6+
7+
-type flow_path() :: [#{DatapathId :: binary() =>
8+
list({OFVersion :: 4 | 5, [flow_mod()]})
9+
}].
10+
11+
-type of_version() :: 4 | 5.
12+
13+
-type flow_mod() :: {Matches :: [term()],
14+
Instructions :: [term()],
15+
Opts :: [term()]}.
16+

src/dobby_oflib.erl

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,7 @@
1212
publish_new_flow/3]).
1313

1414
-include_lib("dobby_clib/include/dobby.hrl").
15-
16-
%% -define(MYMAC, "MY").
17-
18-
%%------------------------------------------------------------------------------
19-
%% Types
20-
%%------------------------------------------------------------------------------
21-
22-
-type openflow_path() ::
23-
[#{DatapathId :: binary() =>
24-
list({OFVersion :: 4 | 5, [flow_mod()]})
25-
}].
26-
27-
-type flow_mod() :: {Matches :: [term()],
28-
Instructions :: [term()],
29-
Opts :: [term()]}.
15+
-include("dobby_oflib.hrl").
3016

3117
%%%=============================================================================
3218
%%% External functions
@@ -42,22 +28,22 @@ get_path(SrcEndpoint, DstEndpoint) ->
4228
%%
4329
%% Publishes a NetFlow identifier between `SrcEndpoint' and `DstEndpoint'
4430
%% that are assumed to be present in Dobby database. It also publishes
45-
%% `OpenFlowPath' that is set of links and identifiers representing OpenFlow
31+
%% `FlowPath' that is set of links and identifiers representing OpenFlow
4632
%% entities that provide logical connectivity between the two endpoints.
47-
%% The first and the last identifiers of the `OpenFlowPath' hang off
33+
%% The first and the last identifiers of the `FlowPath' hang off
4834
%% the Net Flow Identifier and their connections to it indicate the beginning
49-
%% an the end of the `OpenFlowPath'.
35+
%% an the end of the `FlowPath'.
5036
%%
5137
%% The function returns Net Flow Identifier: `NetFlowId' that can be
5238
%% used for referencing published Net Flow.
53-
-spec publish_new_flow(identifier(), identifier(), openflow_path()) ->
39+
-spec publish_new_flow(identifier(), identifier(), flow_path()) ->
5440
Result when
5541
Result :: {ok, NetFlowId :: endpoint()}
5642
| {error, Reason :: term()}.
5743

58-
publish_new_flow(SrcEndpoint, DstEndpoint, OpenFlowPath) ->
59-
NfId = publish_net_flow_identifer(SrcEndpoint, DstEndpoint),
60-
publish_openflow_path(NfId, OpenFlowPath),
44+
publish_new_flow(SrcEndpoint, DstEndpoint, FlowPath) ->
45+
NfId = publish_net_flow_identifier(SrcEndpoint, DstEndpoint),
46+
publish_flow_path(NfId, FlowPath),
6147
lager:info("Published NetFlow: ~p between endpoints src: ~p dst: ~p ~n",
6248
[NfId, SrcEndpoint, DstEndpoint]),
6349
NfId.
@@ -66,54 +52,52 @@ publish_new_flow(SrcEndpoint, DstEndpoint, OpenFlowPath) ->
6652
%%% Internal functions
6753
%%%=============================================================================
6854

69-
publish_net_flow_identifer(Src, Dst) ->
55+
publish_net_flow_identifier(Src, Dst) ->
7056
%% TODO: In transaction
71-
NfNode = {NfId, _NfMetadata} = net_flow_identifier(Src, Dst),
72-
publish(Src, NfNode, link_metadata(ep_to_nf, Src)),
73-
publish(NfId, Dst, link_metadata(ep_to_nf, NfId)),
57+
NfNode = {NfId, _NfMetadata} = dofl_identifier:net_flow(Src, Dst),
58+
publish(Src, NfNode,
59+
dofl_link_metadata:endpoint_with_net_flow(Src)),
60+
publish(NfId, Dst,
61+
dofl_link_metadata:endpoint_with_net_flow(NfId)),
7462
NfId.
7563

76-
publish_openflow_path(NetFlowId, OpenFlowPath0) ->
77-
FlowPath1 = flatten_openflow_path(OpenFlowPath0),
78-
publish_openflow_path(NetFlowId, FlowPath1, NetFlowId).
64+
publish_flow_path(NetFlowId, FlowPath0) ->
65+
FlowPath1 = reconstruct_flow_path(FlowPath0),
66+
publish_flow_path(NetFlowId, FlowPath1, NetFlowId).
7967

80-
publish_openflow_path(NetFlowId, [ExtendedFlowMod | T], LastId)
68+
publish_flow_path(NetFlowId, [ExtendedFlowMod | T], LastId)
8169
when LastId =:= NetFlowId ->
8270
publish(NetFlowId,
8371
{Id, _Md} = flow_mod_identifier(ExtendedFlowMod),
84-
link_metadata(of_path_starts_at, {NetFlowId, NetFlowId})),
85-
publish_openflow_path(NetFlowId, T, Id);
86-
publish_openflow_path(NetFlowId, [ExtendedFlowMod | T], LastId) ->
72+
dofl_link_metadata:net_flow_with_flow_mod(NetFlowId, NetFlowId)),
73+
publish(Id,
74+
flow_table_identifier(ExtendedFlowMod),
75+
dofl_link_metadata:flow_mod_with_flow_table()),
76+
publish_flow_path(NetFlowId, T, Id);
77+
publish_flow_path(NetFlowId, [ExtendedFlowMod | T], LastId) ->
8778
publish(LastId,
8879
{Id, _Md} = flow_mod_identifier(ExtendedFlowMod),
89-
link_metadata(of_path_forwards_to, {NetFlowId, LastId})),
90-
publish_openflow_path(NetFlowId, T, Id);
91-
publish_openflow_path(NetFlowId, [], LastId) ->
80+
dofl_link_metadata:between_flow_mods(LastId, NetFlowId)),
81+
publish(Id,
82+
flow_table_identifier(ExtendedFlowMod),
83+
dofl_link_metadata:flow_mod_with_flow_table()),
84+
publish_flow_path(NetFlowId, T, Id);
85+
publish_flow_path(NetFlowId, [], LastId) ->
9286
publish(LastId, NetFlowId,
93-
link_metadata(of_path_ends_at, {NetFlowId, LastId})).
94-
95-
net_flow_identifier(Src, Dst) ->
96-
{<<"NF:", Src/binary, ":", Dst/binary>>, #{type => of_net_flow}}.
87+
dofl_link_metadata:net_flow_with_flow_mod(LastId, NetFlowId)).
9788

9889
flow_mod_identifier({Dpid, OFVersion, FlowMod}) ->
99-
{_Matches, _Instructions, Opts} = FlowMod,
100-
Cookie = proplists:get_value(cookie, Opts),
101-
{Cookie, #{type => of_flow_mod, dpid => Dpid, of_version => OFVersion}}.
102-
103-
link_metadata(Type = ep_to_nf, SrcIdentifier) ->
104-
#{type => Type, src => SrcIdentifier};
105-
link_metadata(Type, {NetFlowId, Src})
106-
when Type =:= of_path_starts_at;
107-
Type =:= of_path_ends_at;
108-
Type =:= of_path_forwards_to ->
109-
#{type => Type, src => Src, net_flow_ids => [NetFlowId]}.
90+
dofl_identifier:flow_mod(Dpid, OFVersion, FlowMod).
91+
92+
flow_table_identifier({Dpid, _OFVersion, FlowMod}) ->
93+
dofl_identifier:flow_table(Dpid, FlowMod).
11094

11195
publish(Src, Dst, LinkMetadata) ->
11296
dby:publish(Src, Dst, LinkMetadata, [persistent]).
11397

114-
flatten_openflow_path(FlowPath0) ->
98+
reconstruct_flow_path(FlowPath0) ->
11599
Fun = fun({Dpid, {OFVersion, FlowMods}}) ->
116-
[{Dpid, OFVersion, FlowMod} || FlowMod <- FlowMods]
100+
[{Dpid, OFVersion, FM} || FM <- FlowMods]
117101
end,
118102
FlowPath1 = lists:map(Fun, FlowPath0),
119103
lists:flatten(FlowPath1).

src/dofl_identifier.erl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
%%%=============================================================================
2+
%%% @copyright (C) 2015, Erlang Solutions Ltd
3+
%%% @author Szymon Mentel <szymon.mentel@erlang-solutions.com>
4+
%%% @doc <Module purpose>
5+
%%% @end
6+
%%%=============================================================================
7+
-module(dofl_identifier).
8+
-copyright("2015, Erlang Solutions Ltd.").
9+
10+
-export([]).
11+
12+
%% API
13+
-export([net_flow/2,
14+
flow_mod/3,
15+
flow_table/2]).
16+
17+
-include_lib("dobby_clib/include/dobby.hrl").
18+
-include("dobby_oflib.hrl").
19+
20+
%%%=============================================================================
21+
%%% External functions
22+
%%%=============================================================================
23+
24+
-spec net_flow(Src :: identifier(), Dst :: identifier()) -> NetFlow :: endpoint().
25+
26+
net_flow(Src, Dst) ->
27+
{<<"NF:", Src/binary, ":", Dst/binary>>, #{type => of_net_flow}}.
28+
29+
-spec flow_mod(Dpid :: binary(), OFVersion :: of_version(), FlowMod :: flow_mod())
30+
-> FlowModId :: endpoint().
31+
32+
flow_mod(Dpid, OFVersion, FlowMod) ->
33+
{_Matches, _Instructions, Opts} = FlowMod,
34+
Cookie = proplists:get_value(cookie, Opts),
35+
{Cookie, #{type => of_flow_mod, dpid => Dpid, of_version => OFVersion}}.
36+
37+
38+
-spec flow_table(Dpid :: binary(), FlowMod :: flow_mod())
39+
-> FlowTableId :: idenfier().
40+
41+
flow_table(Dpid, FlowMod) ->
42+
<<Dpid/binary>>.
43+
44+
%%%=============================================================================
45+
%%% Internal functions
46+
%%%=============================================================================

src/dofl_link_metadata.erl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
%%%=============================================================================
2+
%%% @copyright (C) 2015, Erlang Solutions Ltd
3+
%%% @author Szymon Mentel <szymon.mentel@erlang-solutions.com>
4+
%%% @doc <Module purpose>
5+
%%% @end
6+
%%%=============================================================================
7+
-module(dofl_link_metadata).
8+
-copyright("2015, Erlang Solutions Ltd.").
9+
10+
%% API
11+
-export([endpoint_with_net_flow/1,
12+
net_flow_with_flow_mod/2,
13+
between_flow_mods/2,
14+
flow_mod_with_flow_table/0]).
15+
16+
17+
-include_lib("dobby_clib/include/dobby.hrl").
18+
-include("dobby_oflib.hrl").
19+
20+
%%%=============================================================================
21+
%%% External functions
22+
%%%=============================================================================
23+
24+
-spec endpoint_with_net_flow(Src :: identifier()) -> Metadata :: map().
25+
26+
endpoint_with_net_flow(Src) ->
27+
#{type => ep_to_nf, src => Src}.
28+
29+
30+
-spec net_flow_with_flow_mod(Src :: identifier(), NetFlowId :: identifier())
31+
-> Metadata :: map().
32+
33+
net_flow_with_flow_mod(Src, NetFlowId) when Src =:= NetFlowId ->
34+
#{type => of_path_starts_at, src => Src, net_flow_ids => [NetFlowId]};
35+
net_flow_with_flow_mod(Src, NetFlowId) ->
36+
#{type => of_path_ends_at, src => Src, net_flow_ids => [NetFlowId]}.
37+
38+
39+
-spec between_flow_mods(Src :: identifier(), NetFlowId :: identifier()) ->
40+
Metadata :: map().
41+
42+
between_flow_mods(Src, NetFlowId) ->
43+
#{type => of_path_forwards_to, src => Src, net_flow_ids => [NetFlowId]}.
44+
45+
-spec flow_mod_with_flow_table() -> Metadata :: map().
46+
47+
flow_mod_with_flow_table() ->
48+
#{type => of_resource}.
49+
50+
%%%=============================================================================
51+
%%% Internal functions
52+
%%%=============================================================================

test/dobby_oflib_SUITE.erl

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
-include_lib("common_test/include/ct.hrl").
1313
-include_lib("eunit/include/eunit.hrl").
1414

15+
-define(SRC_EP, <<"Src">>).
16+
-define(DST_EP, <<"Dst">>).
17+
1518
%%%=============================================================================
1619
%%% Callbacks
1720
%%%=============================================================================
@@ -22,14 +25,16 @@ suite() ->
2225

2326
init_per_suite(Config) ->
2427
mock_dobby(),
28+
mock_flow_table_identifiers(),
2529
Config.
2630

2731
end_per_suite(_Config) ->
2832
unmock_dobby(),
2933
ok.
3034

3135
all() ->
32-
[should_publish_net_flow].
36+
[should_publish_net_flow,
37+
should_publish_flow_path].
3338

3439
%%%=============================================================================
3540
%%% Testcases
@@ -38,15 +43,23 @@ all() ->
3843
should_publish_net_flow(_Config) ->
3944
%% GIVEN
4045
FlowPath = dofl_test_utils:flow_path(),
41-
SrcEP = <<"Src">>,
42-
DstEP = <<"Dst">>,
4346

4447
%% WHEN
45-
NetFlowId = dobby_oflib:publish_new_flow(SrcEP, DstEP, FlowPath),
48+
NetFlowId = dobby_oflib:publish_new_flow(?SRC_EP, ?DST_EP, FlowPath),
49+
50+
%% THEN
51+
assert_net_flow_published(?SRC_EP, ?DST_EP, NetFlowId).
52+
53+
should_publish_flow_path(_Config) ->
54+
%% GIVEN
55+
FlowPath0 = dofl_test_utils:flow_path(),
56+
FlowPath1 = reconstruct_flow_path(FlowPath0),
57+
58+
%% WHEN
59+
NetFlowId = dobby_oflib:publish_new_flow(?SRC_EP, ?DST_EP, FlowPath0),
4660

4761
%% THEN
48-
assert_net_flow_published(SrcEP, DstEP, NetFlowId),
49-
assert_flow_path_published(NetFlowId, FlowPath).
62+
assert_flow_path_published(NetFlowId, FlowPath1).
5063

5164
%%%=============================================================================
5265
%%% Assertions
@@ -63,19 +76,23 @@ assert_net_flow_published(SrcEP, DstEP, NetFlowId) ->
6376

6477

6578
assert_flow_path_published(NetFlowId, FlowPath) ->
66-
FlatFlowPath = flatten_flow_path(FlowPath),
67-
assert_flow_path_published(NetFlowId, FlatFlowPath,
68-
_PrevIdentifier = NetFlowId).
79+
assert_flow_path_published(NetFlowId, FlowPath, _PrevId = NetFlowId).
6980

7081
assert_flow_path_published(NetFlowId, [FlowMod | T], NetFlowId) ->
7182
LinkMd = link_metadata(of_path_starts_at, {NetFlowId, NetFlowId}),
83+
LinkMd2 = link_metadata(of_resource, bidirectional),
7284
FmNode = {FmId,_FmMD} = flow_mod_identifier(FlowMod),
85+
FtId = flow_table_identifier(FlowMod),
7386
?assert(meck:called(dby, publish, [NetFlowId, FmNode, LinkMd, [persistent]])),
87+
?assert(meck:called(dby, publish, [FmId, FtId, LinkMd2, [persistent]])),
7488
assert_flow_path_published(NetFlowId, T, FmId);
7589
assert_flow_path_published(NetFlowId, [FlowMod | T], LastId) ->
7690
LinkMd = link_metadata(of_path_forwards_to, {NetFlowId, LastId}),
91+
LinkMd2 = link_metadata(of_resource, bidirectional),
7792
FmNode = {FmId,_FmMD} = flow_mod_identifier(FlowMod),
93+
FtId = flow_table_identifier(FlowMod),
7894
?assert(meck:called(dby, publish, [LastId, FmNode, LinkMd, [persistent]])),
95+
?assert(meck:called(dby, publish, [FmId, FtId, LinkMd2, [persistent]])),
7996
assert_flow_path_published(NetFlowId, T, FmId);
8097
assert_flow_path_published(NetFlowId, [], LastId) ->
8198
LinkMd = link_metadata(of_path_ends_at, {NetFlowId, LastId}),
@@ -91,21 +108,41 @@ mock_dobby() ->
91108
unmock_dobby() ->
92109
ok = meck:unload(dby).
93110

94-
flow_mod_identifier({Dpid, OFVersion, FlowMod}) ->
111+
mock_flow_table_identifiers() ->
112+
ok = meck:expect(dofl_identifier, flow_table,
113+
fun(Dpid, _FlowMod = {_, _, Opts}) ->
114+
TableNo = proplists:get_value(table_id, Opts),
115+
TableNoBin = integer_to_binary(TableNo),
116+
<<Dpid/binary, ":", TableNoBin/binary>>
117+
end).
118+
119+
flow_mod_identifier({Dpid, OFVersion, _FlowTableId, FlowMod}) ->
95120
{_Matches, _Instructions, Opts} = FlowMod,
96121
Cookie = proplists:get_value(cookie, Opts),
97122
{Cookie, #{type => of_flow_mod, dpid => Dpid, of_version => OFVersion}}.
98123

124+
flow_table_identifier({Dpid, _OFVersion, TableNo, _FlowMod}) ->
125+
TableNoBin = integer_to_binary(TableNo),
126+
<<Dpid/binary, ":", TableNoBin/binary>>.
127+
99128
link_metadata(Type, {NetFlowId, Src}) ->
100-
#{type => Type, src => Src, net_flow_ids => [NetFlowId]}.
129+
#{type => Type, src => Src, net_flow_ids => [NetFlowId]};
130+
link_metadata(Type, bidirectional) ->
131+
#{type => Type}.
101132

102-
flatten_flow_path(FlowPath0) ->
133+
134+
reconstruct_flow_path(FlowPath0) ->
103135
Fun = fun({Dpid, {OFVersion, FlowMods}}) ->
104-
[{Dpid, OFVersion, FlowMod} || FlowMod <- FlowMods]
136+
[reconstruct_flow_mod(Dpid, OFVersion, FM) || FM <- FlowMods]
105137
end,
106138
FlowPath1 = lists:map(Fun, FlowPath0),
107139
lists:flatten(FlowPath1).
108140

141+
reconstruct_flow_mod(Dpid, OFVersion, FlowMod) ->
142+
TableNo = proplists:get_value(table_id, _Opts = element(3, FlowMod)),
143+
{Dpid, OFVersion, TableNo, FlowMod}.
109144

110-
111-
145+
trace_dby_publish() ->
146+
{module, M} = code:ensure_loaded(M = dby),
147+
ct:pal("Matched traces: ~p~n",
148+
[recon_trace:calls({dby, publish, '_'}, 10, [{pid, all}])]).

0 commit comments

Comments
 (0)