From 507533ac3d7b4498d15f29e0098ce6a75590aa21 Mon Sep 17 00:00:00 2001 From: Anita Zhang Date: Fri, 25 Feb 2022 11:39:27 -0800 Subject: Network: Add support for parsing multipath routing (#1736) Signed-off-by: Anita Zhang --- lib/ohai/plugins/linux/network.rb | 17 ++++++++++++-- spec/unit/plugins/linux/network_spec.rb | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/ohai/plugins/linux/network.rb b/lib/ohai/plugins/linux/network.rb index 90c55888..4a5ddb3c 100644 --- a/lib/ohai/plugins/linux/network.rb +++ b/lib/ohai/plugins/linux/network.rb @@ -80,9 +80,22 @@ Ohai.plugin(:Network) do line.strip! logger.trace("Plugin Network: Parsing #{line}") if /\\/.match?(line) + # If we have multipath routing, then the first part will be a normal + # looking route: + # default proto ra metric 1024 + # Each successive part after that is a hop without those options. + # So the first thing we do is grab that first part, and split it into + # the route destination ("default"), and the route options. parts = line.split("\\") - route_dest = parts.shift.strip - route_endings = parts + route_dest, dest_opts = parts.first.split(nil, 2) + # Then all the route endings, generally just nexthops. + route_endings = parts[1..] + if dest_opts && !dest_opts.empty? + # Route options like proto, metric, etc. only appear once for each + # multipath configuration. Prepend this information to the route + # endings so the code below will assign the fields properly. + route_endings.map! { |e| e.include?("nexthop") ? "#{dest_opts} #{e}" : e } + end elsif line =~ /^([^\s]+)\s(.*)$/ route_dest = $1 route_endings = [$2] diff --git a/spec/unit/plugins/linux/network_spec.rb b/spec/unit/plugins/linux/network_spec.rb index f0a7ebf3..48f84ffc 100644 --- a/spec/unit/plugins/linux/network_spec.rb +++ b/spec/unit/plugins/linux/network_spec.rb @@ -1219,6 +1219,46 @@ describe Ohai::System, "Linux Network Plugin" do end end + describe "when there're multipath routes" do + let(:linux_ip_route) do + <<~EOM + 10.5.4.0/24 proto static \\ nexthop via 10.5.4.1 dev eth0 weight 1\\ nexthop via 10.5.4.2 dev eth0 weight 1 + EOM + end + + let(:linux_ip_route_inet6) do + <<~EOM + default proto ra metric 1024 expires 1797sec \\ nexthop via fe80::c018:50ff:fe41:ca33 dev eth0.11 weight 1 \\ nexthop via fe80::c018:50ff:fe41:ca33 dev eth0 weight 1 pref medium + default proto ra metric 1050 expires 1796sec \\ nexthop via fe80::c018:50ff:fe3f:9184 dev eth3 weight 1 \\ nexthop via fe80::c018:50ff:fe3f:9184 dev eth13 weight 1 pref medium + EOM + end + + before do + plugin.run + end + + it "completes the run" do + expect(plugin.logger).not_to receive(:trace).with(/Plugin linux::network threw exception/) + expect(plugin["network"]).not_to be_nil + end + + it "sets default ipv6 interface and gateway" do + expect(plugin["network"]["default_inet6_interface"]).to eq("eth0") + expect(plugin["network"]["default_inet6_gateway"]).to eq("fe80::c018:50ff:fe41:ca33") + end + + it "sets the routes properly" do + expect(plugin["network"]["interfaces"]["eth0"]["routes"]).to eq([ + Mash.new( destination: "10.5.4.0/24", family: "inet", proto: "static", via: "10.5.4.1" ), + Mash.new( destination: "10.5.4.0/24", family: "inet", proto: "static", via: "10.5.4.2" ), + Mash.new( destination: "default", family: "inet6", proto: "ra", via: "fe80::c018:50ff:fe41:ca33", metric: "1024" ), + ]) + expect(plugin["network"]["interfaces"]["eth0.11"]["routes"]).to eq([Mash.new( destination: "default", family: "inet6", proto: "ra", via: "fe80::c018:50ff:fe41:ca33", metric: "1024" )]) + expect(plugin["network"]["interfaces"]["eth13"]["routes"]).to eq([Mash.new( destination: "default", family: "inet6", proto: "ra", via: "fe80::c018:50ff:fe3f:9184", metric: "1050" )]) + expect(plugin["network"]["interfaces"]["eth3"]["routes"]).to eq([Mash.new( destination: "default", family: "inet6", proto: "ra", via: "fe80::c018:50ff:fe3f:9184", metric: "1050" )]) + end + end + describe "when there's a source field in a local route entry but it isnt in the default route" do let(:linux_ip_route) do <<~EOM -- cgit v1.2.1