Skip to content

Commit 4d8f945

Browse files
committed
Merge pull request #187 from frenetic-lang/gorges-tables
Gorges tables
2 parents 4bfb036 + 4ecf9bd commit 4d8f945

File tree

2 files changed

+164
-3
lines changed

2 files changed

+164
-3
lines changed

lib/SDN_Types.ml

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,170 @@ let format_flowTable (fmt:Format.formatter) (l:flowTable) : unit =
397397
format_flow fmt f;
398398
true) false l in
399399
Format.fprintf fmt "]@]"
400-
400+
401401
let string_of_action = make_string_of format_action
402402
let string_of_seq = make_string_of format_seq
403403
let string_of_par = make_string_of format_par
404404
let string_of_flow = make_string_of format_flow
405-
let string_of_flowTable = make_string_of format_flowTable
405+
406+
let string_of_vlan (x : int) : string =
407+
Format.sprintf "Vlan = %d" x
408+
409+
let string_of_vlanpcp (x : dlVlanPcp) : string =
410+
Format.sprintf "VlanPcp = %d" x
411+
412+
let string_of_ethType (x : dlTyp) : string =
413+
let extra = if x = 0x800 then " (ip)"
414+
else if x = 0x806 then " (arp)"
415+
else ""
416+
in
417+
Format.sprintf "EthType = 0x%x%s" x extra
418+
419+
let string_of_ipProto (x : nwProto) : string =
420+
let extra = match x with
421+
| 0x01 -> " (icmp)"
422+
| 0x02 -> " (igmp)"
423+
| 0x06 -> " (tcp)"
424+
| 0x11 -> " (udp)"
425+
| _ -> ""
426+
in
427+
Format.sprintf "ipProto = 0x%x%s" x extra
428+
429+
let string_of_ethSrc (x : dlAddr) : string =
430+
Format.sprintf "EthSrc = %s" (Packet.string_of_mac x)
431+
432+
let string_of_ethDst (x : dlAddr) : string =
433+
Format.sprintf "EthDst = %s" (Packet.string_of_mac x)
434+
435+
let string_of_ip4src (x : Pattern.Ip.t) : string =
436+
Format.sprintf "IP4Src = %s" (Pattern.Ip.string_of x)
437+
438+
let string_of_ip4dst (x : Pattern.Ip.t) : string =
439+
Format.sprintf "IP4Dst = %s" (Pattern.Ip.string_of x)
440+
441+
let string_of_tcpSrcPort (x : tpPort) : string =
442+
Format.sprintf "TCPSrcPort = %d" x
443+
444+
let string_of_tcpDstPort (x : tpPort) : string =
445+
Format.sprintf "TCPDstPort = %d" x
446+
447+
let string_of_inPort (x : portId) : string =
448+
Format.sprintf "InPort = %lu" x
449+
450+
let check (string_of : 'a -> string)
451+
(x : 'a option)
452+
(acc : string list) : string list =
453+
match x with
454+
| None -> acc
455+
| Some x' -> (string_of x') :: acc
456+
457+
(* Builds up a list of strings one for each pattern *)
458+
let pattern_list (p : Pattern.t) : string list =
459+
check string_of_ethSrc p.dlSrc [] |>
460+
check string_of_ethDst p.dlDst |>
461+
check string_of_ethType p.dlTyp |>
462+
check string_of_vlan p.dlVlan |>
463+
check string_of_vlanpcp p.dlVlanPcp |>
464+
check string_of_ip4src p.nwSrc |>
465+
check string_of_ip4dst p.nwDst |>
466+
check string_of_ipProto p.nwProto |>
467+
check string_of_tcpSrcPort p.tpSrc |>
468+
check string_of_tcpDstPort p.tpDst |>
469+
check string_of_inPort p.inPort
470+
471+
(* Given a flow, return a pair of list of strings where the first list
472+
* contains the strings of the pattern and the second list contains
473+
* the strings of the actions associated with the pattern. *)
474+
let to_entry (f : flow) : (string list) * (string list) =
475+
let open Core.Std in
476+
let open List in
477+
let pattern_list = pattern_list f.pattern in
478+
let action_list = map (concat (concat f.action)) string_of_action in
479+
(pattern_list, action_list)
480+
481+
(* Pads a string with spaces so that it is atleast `len` characters. *)
482+
let pad (len : int) (e : string) : string =
483+
let open Core.Std in
484+
let padding_size = max 0 (len - (String.length e)) in
485+
let padding = String.make padding_size ' ' in
486+
String.concat [e; padding]
487+
488+
(* Helper function *)
489+
let unwrap x =
490+
match x with
491+
| None -> 0
492+
| Some x -> x
493+
494+
(* Given a list of entries to be displayed in the table, calculate a pair
495+
* containing the max characters in a pattern string and action string *)
496+
let table_size (label : string) (entries : ((string list) * (string list)) list) : int * int =
497+
let open Core.Std in
498+
let open List in
499+
let patterns = map entries fst |> concat in
500+
let actions = map entries snd |> concat in
501+
let max_p = max_elt (map patterns String.length) (-) |> unwrap in
502+
let max_a = max_elt (map actions String.length) (-) |> unwrap in
503+
(max max_p ((String.length label) + 3 + (String.length "Pattern")), max max_a (String.length "Action"))
504+
505+
(* Create the top edge of the table *)
506+
let top max_p max_a : string =
507+
let open Core.Std in
508+
let open Char in
509+
let fill = String.make (max_p + max_a + 5) '-' in
510+
Format.sprintf "+%s+\n" fill
511+
512+
(* Create the bottom edge of the table *)
513+
let bottom max_p max_a : string=
514+
let open Core.Std in
515+
let fill = String.make (max_p + max_a + 5) '-' in
516+
Format.sprintf "+%s+\n" fill
517+
518+
(* Create a divider between entries *)
519+
let div max_p max_a : string =
520+
let open Core.Std in
521+
let fill = String.make (max_p + max_a + 5) '-' in
522+
Format.sprintf "|%s|\n" fill
523+
524+
(* Create the columns of the table *)
525+
let title label max_p max_a : string =
526+
let open Core.Std in
527+
let pattern = pad max_p (Format.sprintf "%s | Pattern" label) in
528+
let action = pad max_a "Action" in
529+
Format.sprintf "| %s | %s |\n" pattern action
530+
531+
(* Create a row in the table *)
532+
let string_of_entry (max_p : int) (max_a : int) (e : (string list) * (string list)) : string =
533+
let open Core.Std in
534+
let open List in
535+
let padded_patterns = map (fst e) (pad max_p) in
536+
let padded_actions = map (snd e) (pad max_a) in
537+
let blank_action = String.make max_a ' ' in
538+
let blank_pattern = String.make max_p ' ' in
539+
let rec helper pats acts acc =
540+
match pats, acts with
541+
| [], [] -> if (length acc) = 1
542+
then (Format.sprintf "| %s | %s |\n" blank_pattern blank_action) :: acc
543+
else acc
544+
| (p::ps), [] ->
545+
let acc' = (Format.sprintf "| %s | %s |\n" p blank_action) :: acc in
546+
helper ps [] acc'
547+
| [], (a::rest) ->
548+
let acc' = (Format.sprintf "| %s | %s |\n" blank_pattern a) :: acc in
549+
helper [] rest acc'
550+
| (p::ps), (a::rest) ->
551+
let acc' = (Format.sprintf "| %s | %s |\n" p a) :: acc in
552+
helper ps rest acc'
553+
in
554+
helper padded_patterns padded_actions [(div max_p max_a)]
555+
|> rev |> String.concat
556+
557+
(* Given a label and a flowTable, returns an ascii flowtable *)
558+
let string_of_flowTable ?(label="") (tbl : flowTable) : string =
559+
let open Core.Std in
560+
let entries = List.map tbl to_entry in
561+
let (max_p, max_a) = table_size label entries in
562+
let t = (top max_p max_a) in
563+
let l = (title label max_p max_a) in
564+
let entry_strings = List.map entries (string_of_entry max_p max_a) in
565+
let b = bottom max_p max_a in
566+
String.concat (t :: l :: (List.append entry_strings [b]))

lib/SDN_Types.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,4 @@ val string_of_action : action -> string
217217
val string_of_seq : seq -> string
218218
val string_of_par : par -> string
219219
val string_of_flow : flow -> string
220-
val string_of_flowTable : flowTable -> string
220+
val string_of_flowTable : ?label:string -> flowTable -> string

0 commit comments

Comments
 (0)