Skip to content

Commit 45df4b1

Browse files
committed
Remove usages of List.hd
List.hd can raise exceptions in locations where they are not expected. Quite a few deals with string splits, these can be worked around to not use lists at all. Others need to raise a semantically-correct error to properly debug the issue. Signed-off-by: Pau Ruiz Safont <[email protected]>
1 parent 12d82b7 commit 45df4b1

File tree

2 files changed

+79
-66
lines changed

2 files changed

+79
-66
lines changed

lib/network_utils.ml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@ module Sysfs = struct
161161

162162
let read_one_line file =
163163
try
164-
Unixext.string_of_file file |> String.split_on_char '\n' |> List.hd
165-
(* Note: the list returned by split_on_char is guaranteed to be non-empty *)
164+
Unixext.string_of_file file |> Astring.String.take ~sat:(( <> ) '\n')
166165
with
167166
| End_of_file ->
168167
""
@@ -204,7 +203,7 @@ module Sysfs = struct
204203
let get_pcibuspath name =
205204
try
206205
let devpath = Unix.readlink (getpath name "device") in
207-
List.hd (List.rev (Astring.String.cuts ~empty:false ~sep:"/" devpath))
206+
Filename.basename devpath
208207
with _ -> "N/A"
209208

210209
let get_pci_ids name =
@@ -785,9 +784,7 @@ module Linux_bonding = struct
785784
let master_path = Unix.readlink master_symlink in
786785
let slaves_path = Filename.concat master_symlink "bonding/slaves" in
787786
Unix.access slaves_path [Unix.F_OK] ;
788-
Some
789-
(List.hd
790-
(List.rev (Astring.String.cuts ~empty:false ~sep:"/" master_path)))
787+
Some (Filename.basename master_path)
791788
with _ -> None
792789

793790
let get_bond_active_slave master =
@@ -806,9 +803,12 @@ module Linux_bonding = struct
806803
Sysfs.read_one_line (Sysfs.getpath master ("bonding/" ^ prop))
807804
in
808805
if prop = "mode" then
809-
Some
810-
( prop
811-
, List.hd (Astring.String.cuts ~empty:false ~sep:" " bond_prop) )
806+
let get_mode line =
807+
let a_space char = char = ' ' in
808+
Astring.String.(
809+
line |> drop ~sat:a_space |> take ~sat:(Fun.negate a_space))
810+
in
811+
Some (prop, get_mode bond_prop)
812812
else
813813
Some (prop, bond_prop)
814814
with _ ->

networkd/network_server.ml

Lines changed: 70 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -903,13 +903,25 @@ module Bridge = struct
903903
()
904904
| Some (parent, vlan) ->
905905
let bridge_interfaces = Sysfs.bridge_to_interfaces name in
906+
let parent_bridge_interfaces =
907+
List.filter
908+
(fun n ->
909+
Astring.String.is_prefix ~affix:"eth" n
910+
|| Astring.String.is_prefix ~affix:"bond" n)
911+
(Sysfs.bridge_to_interfaces parent)
912+
in
906913
let parent_bridge_interface =
907-
List.hd
908-
(List.filter
909-
(fun n ->
910-
Astring.String.is_prefix ~affix:"eth" n
911-
|| Astring.String.is_prefix ~affix:"bond" n)
912-
(Sysfs.bridge_to_interfaces parent))
914+
match parent_bridge_interfaces with
915+
| [] ->
916+
let msg =
917+
Printf.sprintf
918+
{|Interface for bridge parent "%s" of vlan %i not found|}
919+
parent vlan
920+
in
921+
error "%s" msg ;
922+
raise (Network_error (Internal_error msg))
923+
| iface :: _ ->
924+
iface
913925
in
914926
let parent_interface =
915927
if need_enic_workaround () then (
@@ -1130,16 +1142,17 @@ module Bridge = struct
11301142
=
11311143
match !backend_kind with
11321144
| Openvswitch -> (
1133-
if List.length interfaces = 1 then (
1134-
List.iter (fun name -> Interface.bring_up () dbg ~name) interfaces ;
1135-
ignore (Ovs.create_port (List.hd interfaces) bridge)
1136-
) else (
1137-
if bond_mac = None then
1138-
warn "No MAC address specified for the bond" ;
1139-
ignore
1140-
(Ovs.create_bond ?mac:bond_mac name interfaces bridge
1141-
bond_properties) ;
1142-
List.iter (fun name -> Interface.bring_up () dbg ~name) interfaces
1145+
( match interfaces with
1146+
| [iface] ->
1147+
Interface.bring_up () dbg ~name:iface ;
1148+
ignore (Ovs.create_port iface bridge)
1149+
| _ ->
1150+
if bond_mac = None then
1151+
warn "No MAC address specified for the bond" ;
1152+
ignore
1153+
(Ovs.create_bond ?mac:bond_mac name interfaces bridge
1154+
bond_properties) ;
1155+
List.iter (fun name -> Interface.bring_up () dbg ~name) interfaces
11431156
) ;
11441157
if List.mem bridge !add_default then
11451158
let mac =
@@ -1160,39 +1173,39 @@ module Bridge = struct
11601173
no MAC address was specified"
11611174
name bridge
11621175
)
1163-
| Bridge ->
1164-
if List.length interfaces = 1 then
1165-
List.iter (fun name -> Interface.bring_up () dbg ~name) interfaces
1166-
else (
1167-
Linux_bonding.add_bond_master name ;
1168-
let bond_properties =
1169-
if
1170-
List.mem_assoc "mode" bond_properties
1171-
&& List.assoc "mode" bond_properties = "lacp"
1172-
then
1173-
Xapi_stdext_std.Listext.List.replace_assoc "mode" "802.3ad"
1174-
bond_properties
1175-
else
1176-
bond_properties
1177-
in
1178-
Linux_bonding.set_bond_properties name bond_properties ;
1179-
Linux_bonding.set_bond_slaves name interfaces ;
1180-
( match bond_mac with
1181-
| Some mac ->
1182-
Ip.set_mac name mac
1183-
| None ->
1184-
warn "No MAC address specified for the bond"
1176+
| Bridge -> (
1177+
match interfaces with
1178+
| [iface] ->
1179+
Interface.bring_up () dbg ~name:iface
1180+
| _ ->
1181+
( Linux_bonding.add_bond_master name ;
1182+
let bond_properties =
1183+
match List.assoc_opt "mode" bond_properties with
1184+
| Some "lacp" ->
1185+
Xapi_stdext_std.Listext.List.replace_assoc "mode" "802.3ad"
1186+
bond_properties
1187+
| _ ->
1188+
bond_properties
1189+
in
1190+
Linux_bonding.set_bond_properties name bond_properties ;
1191+
Linux_bonding.set_bond_slaves name interfaces ;
1192+
( match bond_mac with
1193+
| Some mac ->
1194+
Ip.set_mac name mac
1195+
| None ->
1196+
warn "No MAC address specified for the bond"
1197+
) ;
1198+
Interface.bring_up () dbg ~name
11851199
) ;
1186-
Interface.bring_up () dbg ~name
1187-
) ;
1188-
if need_enic_workaround () then (
1189-
debug "Applying enic workaround: adding VLAN0 device to bridge" ;
1190-
Ip.create_vlan name 0 ;
1191-
let vlan0 = Ip.vlan_name name 0 in
1192-
Interface.bring_up () dbg ~name:vlan0 ;
1193-
ignore (Brctl.create_port bridge vlan0)
1194-
) else
1195-
ignore (Brctl.create_port bridge name)
1200+
if need_enic_workaround () then (
1201+
debug "Applying enic workaround: adding VLAN0 device to bridge" ;
1202+
Ip.create_vlan name 0 ;
1203+
let vlan0 = Ip.vlan_name name 0 in
1204+
Interface.bring_up () dbg ~name:vlan0 ;
1205+
ignore (Brctl.create_port bridge vlan0)
1206+
) else
1207+
ignore (Brctl.create_port bridge name)
1208+
)
11961209

11971210
let add_pvs_proxy_port dbg bridge name _port =
11981211
match !backend_kind with
@@ -1266,7 +1279,7 @@ module Bridge = struct
12661279
Ovs.get_real_bridge name
12671280
|> Ovs.bridge_to_interfaces
12681281
|> List.filter Sysfs.is_physical
1269-
| Bridge ->
1282+
| Bridge -> (
12701283
let ifaces = Sysfs.bridge_to_interfaces name in
12711284
let vlan_ifaces =
12721285
List.filter
@@ -1281,16 +1294,16 @@ module Bridge = struct
12811294
let physical_ifaces =
12821295
List.filter (fun iface -> Sysfs.is_physical iface) ifaces
12831296
in
1284-
if vlan_ifaces <> [] then
1285-
let _, _, parent = List.hd vlan_ifaces in
1286-
if Linux_bonding.is_bond_device parent then
1297+
match (vlan_ifaces, bond_ifaces) with
1298+
| (_, _, parent) :: _, _ when Linux_bonding.is_bond_device parent ->
12871299
Linux_bonding.get_bond_slaves parent
1288-
else
1300+
| (_, _, parent) :: _, _ ->
12891301
[parent]
1290-
else if bond_ifaces <> [] then
1291-
Linux_bonding.get_bond_slaves (List.hd bond_ifaces)
1292-
else
1293-
physical_ifaces)
1302+
| _, bond_iface :: _ ->
1303+
Linux_bonding.get_bond_slaves bond_iface
1304+
| [], [] ->
1305+
physical_ifaces
1306+
))
12941307
()
12951308

12961309
let set_persistent dbg name value =

0 commit comments

Comments
 (0)