]> git.proxmox.com Git - pve-network.git/blame - PVE/Network/SDN/Controllers/BgpPlugin.pm
controllers: improve bgp-evpn
[pve-network.git] / PVE / Network / SDN / Controllers / BgpPlugin.pm
CommitLineData
f23633dc
AD
1package PVE::Network::SDN::Controllers::BgpPlugin;
2
3use strict;
4use warnings;
5
6use PVE::INotify;
7use PVE::JSONSchema qw(get_standard_option);
8use PVE::Tools qw(run_command file_set_contents file_get_contents);
9
10use PVE::Network::SDN::Controllers::Plugin;
11use PVE::Network::SDN::Zones::Plugin;
12use Net::IP;
13
14use base('PVE::Network::SDN::Controllers::Plugin');
15
16sub type {
17 return 'bgp';
18}
19
20sub properties {
21 return {
22 ebgp => {
23 type => 'boolean',
24 optional => 1,
25 description => "Enable ebgp. (remote-as external)",
26 },
27 loopback => {
28 description => "source loopback interface.",
29 type => 'string'
30 },
31 node => get_standard_option('pve-node'),
32 };
33}
34
35sub options {
36 return {
37 'node' => { optional => 0 },
38 'asn' => { optional => 0 },
39 'peers' => { optional => 0 },
40 'ebgp' => { optional => 1 },
41 'loopback' => { optional => 1 },
42 };
43}
44
45# Plugin implementation
46sub generate_controller_config {
47 my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_;
48
49 my @peers;
50 @peers = PVE::Tools::split_list($plugin_config->{'peers'}) if $plugin_config->{'peers'};
51
52 my $asn = $plugin_config->{asn};
53 my $ebgp = $plugin_config->{ebgp};
54 my $loopback = $plugin_config->{loopback};
55 my $local_node = PVE::INotify::nodename();
56
57
58 return if !$asn;
59 return if $local_node ne $plugin_config->{node};
60
61 my $bgp = $config->{frr}->{router}->{"bgp $asn"} //= {};
62
63 my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
64
65 my $remoteas = $ebgp ? "external" : $asn;
66
67 #global options
68 my @controller_config = (
69 "bgp router-id $ifaceip",
70 "no bgp default ipv4-unicast",
71 "coalesce-time 1000",
72 "bgp network import-check"
73 );
74
75 push(@{$bgp->{""}}, @controller_config) if keys %{$bgp} == 0;
76
77 @controller_config = ();
78 if($ebgp) {
79 push @controller_config, "no bgp ebgp-requires-policy";
80 push @controller_config, "bgp disable-ebgp-connected-route-check" if $loopback;
81 }
82
83 #BGP neighbors
84 if(@peers) {
85 push @controller_config, "neighbor BGP peer-group";
86 push @controller_config, "neighbor BGP remote-as $remoteas";
87 push @controller_config, "neighbor BGP bfd";
88 }
89
90 # BGP peers
91 foreach my $address (@peers) {
92 push @controller_config, "neighbor $address peer-group BGP";
93 }
94 push(@{$bgp->{""}}, @controller_config);
95
96 # address-family unicast
97 if (@peers) {
98 my $ipversion = Net::IP::ip_is_ipv6($ifaceip) ? "ipv6" : "ipv4";
99 my $mask = Net::IP::ip_is_ipv6($ifaceip) ? "/128" : "32";
100
101 push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "network $ifaceip/$mask") if $loopback;
102 push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "neighbor BGP activate");
103 push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "neighbor BGP soft-reconfiguration inbound");
104 }
105
106 return $config;
107}
108
109sub generate_controller_zone_config {
110 my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
111
112}
113
114sub on_delete_hook {
115 my ($class, $controllerid, $zone_cfg) = @_;
116
117 # verify that zone is associated to this controller
118 foreach my $id (keys %{$zone_cfg->{ids}}) {
119 my $zone = $zone_cfg->{ids}->{$id};
120 die "controller $controllerid is used by $id"
121 if (defined($zone->{controller}) && $zone->{controller} eq $controllerid);
122 }
123}
124
125sub on_update_hook {
126 my ($class, $controllerid, $controller_cfg) = @_;
127
128 # we can only have 1 bgp controller by node
129 my $local_node = PVE::INotify::nodename();
130 my $controllernb = 0;
131 foreach my $id (keys %{$controller_cfg->{ids}}) {
132 next if $id eq $controllerid;
133 my $controller = $controller_cfg->{ids}->{$id};
134 next if $controller->{type} ne "bgp";
135 next if $controller->{node} ne $local_node;
136 $controllernb++;
137 die "only 1 bgp controller can be defined" if $controllernb > 1;
138 }
139}
140
141sub write_controller_config {
142 my ($class, $plugin_config, $config) = @_;
143 return;
144}
145
146sub reload_controller {
147 my ($class) = @_;
148 return;
149}
150
1511;
152
153