Skip to content

Commit e976b03

Browse files
committed
CA-120846: fix get_mac for bonded interfaces
When an interface is bonded by the Linux bonding driver, the driver may change the MAC address of the interface to that of the bond. The only place where you can find the "real" MAC address of a bond slave seems to be /proc/net/bonding. Signed-off-by: Rob Hoes <[email protected]>
1 parent afc0a17 commit e976b03

File tree

2 files changed

+41
-15
lines changed

2 files changed

+41
-15
lines changed

lib/network_utils.ml

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,12 @@ module Linux_bonding = struct
445445
error "Failed to remove slave %s from bond %s" slave master
446446
else
447447
error "Bond %s does not exist; cannot remove slave" master
448+
449+
let get_bond_master_of slave =
450+
try
451+
let path = Unix.readlink (Sysfs.getpath slave "master") in
452+
Some (List.hd (List.rev (String.split '/' path)))
453+
with _ -> None
448454
end
449455

450456
module Dhclient = struct
@@ -533,28 +539,46 @@ module Sysctl = struct
533539
end
534540

535541
module Proc = struct
536-
let get_bond_links_up name =
542+
let get_bond_slave_info name key =
537543
try
538544
let raw = Unixext.string_of_file (bonding_dir ^ name) in
539545
let lines = String.split '\n' raw in
540546
let check_lines lines =
541-
let rec loop acc = function
542-
| [] -> acc
543-
| line1 :: line2 :: tail ->
544-
if (String.startswith "Slave Interface:" line1)
545-
&& (String.startswith "MII Status:" line2)
546-
&& (String.endswith "up" line2)
547-
then
548-
loop (acc + 1) tail
549-
else
550-
loop acc (line2 :: tail)
551-
| _ :: [] -> acc in
552-
loop 0 lines in
547+
let rec loop current acc = function
548+
| [] -> acc
549+
| line :: tail ->
550+
try
551+
Scanf.sscanf line "%s@: %s@\n" (fun k v ->
552+
if k = "Slave Interface" then begin
553+
let interface = Some (String.strip String.isspace v) in
554+
loop interface acc tail
555+
end else if k = key then
556+
match current with
557+
| Some interface -> loop current ((interface, String.strip String.isspace v) :: acc) tail
558+
| None -> loop current acc tail
559+
else
560+
loop current acc tail
561+
)
562+
with _ ->
563+
loop current acc tail
564+
in
565+
loop None [] lines
566+
in
553567
check_lines lines
554568
with e ->
555569
error "Error: could not read %s." (bonding_dir ^ name);
556-
0
570+
[]
557571

572+
let get_bond_slave_mac name slave =
573+
let macs = get_bond_slave_info name "Permanent HW addr" in
574+
if List.mem_assoc slave macs then
575+
List.assoc slave macs
576+
else
577+
raise Not_found
578+
579+
let get_bond_links_up name =
580+
let statusses = get_bond_slave_info name "MII Status" in
581+
List.fold_left (fun x (_, y) -> x + (if y = "up" then 1 else 0)) 0 statusses
558582
end
559583

560584
module Ovs = struct

networkd/network_server.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ module Interface = struct
103103

104104
let get_mac _ dbg ~name =
105105
Debug.with_thread_associated dbg (fun () ->
106-
Ip.get_mac name
106+
match Linux_bonding.get_bond_master_of name with
107+
| Some master -> Proc.get_bond_slave_mac master name
108+
| None -> Ip.get_mac name
107109
) ()
108110

109111
let is_up _ dbg ~name =

0 commit comments

Comments
 (0)