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