@@ -397,9 +397,170 @@ let format_flowTable (fmt:Format.formatter) (l:flowTable) : unit =
397
397
format_flow fmt f;
398
398
true ) false l in
399
399
Format. fprintf fmt " ]@]"
400
-
400
+
401
401
let string_of_action = make_string_of format_action
402
402
let string_of_seq = make_string_of format_seq
403
403
let string_of_par = make_string_of format_par
404
404
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]))
0 commit comments