Source file GroupTable0x04.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
open Core
open OpenFlow0x04
open Packet
type t = {
table : (groupId, (groupType * bucket list)) Hashtbl.Poly.t;
mutable next_group_id : groupId;
mutable pending_messages : Message.t list
} [@@deriving sexp]
let to_string t =
let ty_to_str ty = Sexp.to_string (sexp_of_groupType ty) in
let actions_to_str actions =
List.map actions ~f:(fun a -> Sexp.to_string (sexp_of_action a))
|> String.concat ~sep:", "
in
let wpt_to_str = function
| None -> ""
| (Some pt) -> sprintf "watch_port=%ld, " pt
in
let wgr_to_str = function
| None -> ""
| (Some gr) -> sprintf "watch_group=%ld, " gr
in
let bucket_to_str { bu_weight = weight; bu_watch_port = wport;
bu_watch_group = wgroup; bu_actions = actions } =
sprintf " weight %d: %s%sactions=%s" weight
(wpt_to_str wport) (wgr_to_str wgroup) (actions_to_str actions)
in
let buckets_to_str bs = List.map bs ~f:bucket_to_str |> String.concat ~sep:"\n" in
let row_to_str (id, (ty, buckets)) =
sprintf "ID=%ld, Type=%s, Buckets=[\n%s\n]" id (ty_to_str ty) (buckets_to_str buckets)
in
Hashtbl.to_alist t.table
|> List.map ~f:row_to_str
|> String.concat ~sep:"\n"
let next_group_id (tbl : t) =
let id = tbl.next_group_id in
tbl.next_group_id <- Int32.succ id;
if Poly.(tbl.next_group_id = 0l) then
failwith "out of group IDs"
else
id
let create () : t = {
table = Hashtbl.Poly.create () ~size:100;
next_group_id = 1l;
pending_messages = []
}
let add_group (tbl : t) (typ : groupType) (buckets : bucket list) : groupId =
let id = next_group_id tbl in
let msg = Message.GroupModMsg (AddGroup (typ, id, buckets)) in
Hashtbl.add_exn tbl.table id (typ, buckets);
tbl.pending_messages <- msg :: tbl.pending_messages;
id
let clear_groups (tbl : t) : unit =
tbl.next_group_id <- 1l;
let rm_group (id : groupId) ((typ, _) : groupType * bucket list) : unit =
let msg = Message.GroupModMsg (DeleteGroup (typ, id)) in
tbl.pending_messages <- msg :: tbl.pending_messages in
Hashtbl.iteri tbl.table ~f:(fun ~key ~data -> rm_group key data);
Hashtbl.clear tbl.table
let commit (tbl : t) : Message.t list =
let msgs = tbl.pending_messages in
tbl.pending_messages <- [];
List.rev msgs
let port_to_forward_bucket ((port, weight) : portId * int16) =
{ bu_weight = weight;
bu_watch_port = Some port;
bu_watch_group = None;
bu_actions = [Output(PhysicalPort port)] }
let add_fastfail_group (tbl : t) (ports : portId list) =
let open Core in
let buckets = List.zip_exn ports (List.range ~stride:(-1) (List.length ports) 0)
|> List.map ~f:port_to_forward_bucket
in add_group tbl FF buckets