]> git.proxmox.com Git - pve-network.git/commitdiff
sdn: add generate_frr_config
authorAlexandre Derumier <aderumier@odiso.com>
Thu, 29 Aug 2019 10:32:51 +0000 (12:32 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 3 Sep 2019 06:22:56 +0000 (08:22 +0200)
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
PVE/Network/SDN.pm
PVE/Network/SDN/FrrPlugin.pm
PVE/Network/SDN/VlanPlugin.pm
PVE/Network/SDN/VxlanPlugin.pm
test/generateconfig.pl

index 9d8006ef7b0427475881e7bae6bcf8d362ef8db2..80a70d860ccb160feb8b2a97ec058dde93fc850d 100644 (file)
@@ -149,27 +149,103 @@ sub generate_etc_network_config {
        $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $uplinks, $config);
     }
 
-    my $network_config = $config->{network};
     my $raw_network_config = "";
-    foreach my $iface (keys %$network_config) {
+    foreach my $iface (keys %$config) {
        $raw_network_config .= "\n";
        $raw_network_config .= "auto $iface\n";
        $raw_network_config .= "iface $iface\n";
-       foreach my $option (@{$network_config->{$iface}}) {
+       foreach my $option (@{$config->{$iface}}) {
            $raw_network_config .= "\t$option\n";
        }
     }
 
-    my $frr_config = $config->{frr};
-    my $raw_frr_config = "";
-    foreach my $asn (keys %$frr_config) {
-       $raw_frr_config .= "router bgp $asn";
-       foreach my $option (@{$frr_config->{$asn}}) {
+    return $raw_network_config;
+}
+
+sub generate_frr_config {
+
+    my $sdn_cfg = PVE::Cluster::cfs_read_file('sdn.cfg');
+    return if !$sdn_cfg;
+
+    #read main config for physical interfaces
+    my $current_config_file = "/etc/network/interfaces";
+    my $fh = IO::File->new($current_config_file);
+    my $interfaces_config = PVE::INotify::read_etc_network_interfaces(1,$fh);
+    $fh->close();
+
+    #check uplinks
+    my $uplinks = {};
+    foreach my $id (keys %{$interfaces_config->{ifaces}}) {
+       my $interface = $interfaces_config->{ifaces}->{$id};
+       if (my $uplink = $interface->{'uplink-id'}) {
+           die "uplink-id $uplink is already defined on $uplinks->{$uplink}" if $uplinks->{$uplink};
+           $interface->{name} = $id;
+           $uplinks->{$interface->{'uplink-id'}} = $interface;
+       }
+    }
+
+    my $frr_cfg = undef;
+    my $transport_cfg = undef;
+
+    foreach my $id (keys %{$sdn_cfg->{ids}}) {
+       if ($sdn_cfg->{ids}->{$id}->{type} eq 'frr') {
+           $frr_cfg->{ids}->{$id} = $sdn_cfg->{ids}->{$id};
+       } elsif ($sdn_cfg->{ids}->{$id}->{type} ne 'vnet') {
+           $transport_cfg->{ids}->{$id} = $sdn_cfg->{ids}->{$id};
+       }
+    }
+
+    #generate configuration
+    my $config = {};
+
+    foreach my $id (keys %{$frr_cfg->{ids}}) {
+       my $plugin_config = $frr_cfg->{ids}->{$id};
+       my $asn = $plugin_config->{asn};
+       if ($asn) {
+           my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+           $plugin->generate_frr_config($plugin_config, $asn, $id, $uplinks, $config);
+       }
+    }
+
+    foreach my $id (keys %{$transport_cfg->{ids}}) {
+       my $plugin_config = $transport_cfg->{ids}->{$id};
+       my $router = $plugin_config->{router};
+       if ($router) {
+           my $asn = $frr_cfg->{ids}->{$router}->{asn};
+           if ($asn) {
+               my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+               $plugin->generate_frr_config($plugin_config, $asn, $id, $uplinks, $config);
+           }
+       }
+    }
+
+    my $raw_frr_config = "log syslog informational\n";
+    $raw_frr_config .= "!\n";
+
+    #vrf first
+    my $vrfconfig = $config->{vrf};
+    foreach my $vrf (sort keys %$vrfconfig) {
+       $raw_frr_config .= "$vrf\n";
+       foreach my $option (@{$vrfconfig->{$vrf}}) {
            $raw_frr_config .= " $option\n";
        }
+       $raw_frr_config .= "!\n";
     }
 
-    return wantarray ? ($raw_network_config, $raw_frr_config) : $raw_network_config;
+    #routers
+    my $routerconfig = $config->{router};
+    foreach my $router (sort keys %$routerconfig) {
+       $raw_frr_config .= "$router\n";
+       foreach my $option (@{$routerconfig->{$router}}) {
+           $raw_frr_config .= " $option\n";
+       }
+       $raw_frr_config .= "!\n";
+    }
+
+    $raw_frr_config .= "line vty\n";
+    $raw_frr_config .= "!\n";
+
+    return $raw_frr_config;
 }
 
 sub write_etc_network_config {
index 80ca417a5b2cf2d390664e8e7b59f5975798eb35..0ea6d4898db0c59d82b326c8bfcec275ce76f991 100644 (file)
@@ -34,27 +34,23 @@ sub options {
 }
 
 # Plugin implementation
-sub generate_sdn_config {
-    my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_;
+sub generate_frr_config {
+    my ($class, $plugin_config, $asn, $id, $uplinks, $config) = @_;
 
-    my $asn = $plugin_config->{'asn'};
     my @peers = split(',', $plugin_config->{'peers'}) if $plugin_config->{'peers'};
 
     my $uplink = $plugin_config->{'uplink-id'};
 
-    die "missing peers" if !$plugin_config->{'peers'};
-
     my $iface = "uplink$uplink";
     my $ifaceip = "";
 
     if($uplinks->{$uplink}->{name}) {
        $iface = $uplinks->{$uplink}->{name};
-       $ifaceip = get_first_local_ipv4_from_interface($iface);
+        $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface);
     }
 
     my @router_config = ();
 
-    push @router_config, "router bgp $asn";
     push @router_config, "bgp router-id $ifaceip";
     push @router_config, "coalesce-time 1000";
 
@@ -70,11 +66,8 @@ sub generate_sdn_config {
     }
     push @router_config, " advertise-all-vni";
     push @router_config, "exit-address-family";
-    push @router_config, "!";
-    push @router_config, "line vty";
-    push @router_config, "!";
 
-    push(@{$config->{frr}->{$asn}}, @router_config);
+    push(@{$config->{router}->{"router bgp $asn"}}, @router_config);
 
     return $config;
 }
index d2b747597d06ef7469b65305b9e5e7f6a2c24dc3..2af24b7b5d83512f816f2377b9b71dfdaf21e64b 100644 (file)
@@ -77,7 +77,7 @@ sub generate_sdn_config {
     my @iface_config = ();
     push @iface_config, "vlan-protocol $vlanprotocol" if $vlanprotocol;
     push @iface_config, "mtu $mtu" if $mtu;
-    push(@{$config->{network}->{$iface}}, @iface_config) if !$config->{network}->{$iface};
+    push(@{$config->{$iface}}, @iface_config) if !$config->{$iface};
 
     #vnet bridge
     @iface_config = ();
@@ -87,7 +87,7 @@ sub generate_sdn_config {
     push @iface_config, "bridge-vlan-aware yes" if $vlanaware;
     push @iface_config, "mtu $mtu" if $mtu;
     push @iface_config, "alias $alias" if $alias;
-    push(@{$config->{network}->{$vnetid}}, @iface_config) if !$config->{network}->{$vnetid};
+    push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
 
     return $config;
 }
index 6e247a776c89356d0be60aaf689cbb7b8d8f574c..99cd2afd6057f8bb526c8bc0d65ece846d3cd042 100644 (file)
@@ -42,6 +42,10 @@ sub properties {
            type => 'integer',
            description => "l3vni.",
        },
+       'router' => {
+           type => 'string',
+           description => "Frr router name",
+       },
     };
 }
 
@@ -54,6 +58,7 @@ sub options {
         'vxlan-allowed' => { optional => 1 },
         'vrf' => { optional => 1 },
         'vrf-vxlan' => { optional => 1 },
+        'router' => { optional => 1 },
     };
 }
 
@@ -107,7 +112,7 @@ sub generate_sdn_config {
     }
 
     push @iface_config, "mtu $mtu" if $mtu;
-    push(@{$config->{network}->{"vxlan$vnetid"}}, @iface_config) if !$config->{network}->{"vxlan$vnetid"};
+    push(@{$config->{"vxlan$vnetid"}}, @iface_config) if !$config->{"vxlan$vnetid"};
 
     #vnet bridge
     @iface_config = ();
@@ -120,13 +125,13 @@ sub generate_sdn_config {
     push @iface_config, "mtu $mtu" if $mtu;
     push @iface_config, "alias $alias" if $alias;
     push @iface_config, "vrf $vrf" if $vrf;
-    push(@{$config->{network}->{$vnetid}}, @iface_config) if !$config->{network}->{$vnetid};
+    push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
 
     if ($vrf) {
        #vrf intreface
        @iface_config = ();
        push @iface_config, "vrf-table auto";
-       push(@{$config->{network}->{$vrf}}, @iface_config) if !$config->{network}->{$vrf};
+       push(@{$config->{$vrf}}, @iface_config) if !$config->{$vrf};
 
        if ($vrfvxlan) {
            #l3vni vxlan interface
@@ -137,7 +142,7 @@ sub generate_sdn_config {
            push @iface_config, "bridge-learning off";
            push @iface_config, "bridge-arp-nd-suppress on";
            push @iface_config, "mtu $mtu" if $mtu;
-           push(@{$config->{network}->{$iface_vxlan}}, @iface_config) if !$config->{network}->{$iface_vxlan};
+           push(@{$config->{$iface_vxlan}}, @iface_config) if !$config->{$iface_vxlan};
 
            #l3vni bridge
            my $brvrf = "br$vrf";
@@ -147,13 +152,53 @@ sub generate_sdn_config {
            push @iface_config, "bridge_fd 0";
            push @iface_config, "mtu $mtu" if $mtu;
            push @iface_config, "vrf $vrf";
-           push(@{$config->{network}->{$brvrf}}, @iface_config) if !$config->{network}->{$brvrf};
+           push(@{$config->{$brvrf}}, @iface_config) if !$config->{$brvrf};
        }
     }
 
     return $config;
 }
 
+sub generate_frr_config {
+    my ($class, $plugin_config, $asn, $id, $uplinks, $config) = @_;
+
+    my $vrf = $plugin_config->{'vrf'};
+    my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
+    return if !$vrf || !$vrfvxlan;
+
+    my $uplink = $plugin_config->{'uplink-id'};
+
+    my $iface = "uplink$uplink";
+    my $ifaceip = "";
+
+    if($uplinks->{$uplink}->{name}) {
+        $iface = $uplinks->{$uplink}->{name};
+        $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface);
+    }
+
+    #vrf
+    my @router_config = ();
+    push @router_config, "vni $vrfvxlan";
+    push @router_config, "exit-vrf";
+    push(@{$config->{vrf}->{"vrf $vrf"}}, @router_config);
+
+
+    #vrf router
+    @router_config = ();
+    push @router_config, "bgp router-id $ifaceip";
+    push @router_config, "!";
+    push @router_config, "address-family ipv4 unicast";
+    push @router_config, " redistribute connected";
+    push @router_config, "exit-address-family";
+    push @router_config, "!";
+    push @router_config, "address-family l2vpn evpn";
+    push @router_config, " advertise ipv4 unicast";
+    push @router_config, "exit-address-family";
+    push(@{$config->{router}->{"router bgp $asn vrf $vrf"}}, @router_config);
+
+    return $config;
+}
+
 sub on_delete_hook {
     my ($class, $transportid, $sdn_cfg) = @_;
 
index 6d8b80aa467ec33e31a460b7e4b503edb739afcb..6003f94a30abc4770d04062e9238920e61f11444 100644 (file)
@@ -6,7 +6,10 @@ use PVE::Cluster qw(cfs_read_file);
 use PVE::Network::SDN;
 
 
-my ($network_config, $frr_config) = PVE::Network::SDN::generate_etc_network_config();
+my $network_config = PVE::Network::SDN::generate_etc_network_config();
 PVE::Network::SDN::write_etc_network_config($network_config);
 print $network_config;
+
+
+my $frr_config = PVE::Network::SDN::generate_frr_config();
 print $frr_config;