diff --git a/share/oneprovision/ansible/aws.yml b/share/oneprovision/ansible/aws.yml index 57be54058e..8ba0295dc6 100644 --- a/share/oneprovision/ansible/aws.yml +++ b/share/oneprovision/ansible/aws.yml @@ -11,5 +11,13 @@ - opennebula-repository - opennebula-node-kvm - opennebula-ssh - - iptables + - role: iptables + iptables_base_rules_services: + - { protocol: 'tcp', port: 22 } + # TCP/179 bgpd (TODO: only needed on Route Refector(s)) + - { protocol: 'tcp', port: 179 } + # TCP/8742 default VXLAN port on Linux (UDP/4789 default IANA) + - { protocol: 'udp', port: 8472 } - update-replica + - role: frr + frr_iface: 'eth0' diff --git a/share/oneprovision/ansible/packet.yml b/share/oneprovision/ansible/packet.yml index 57be54058e..36d12ae9f4 100644 --- a/share/oneprovision/ansible/packet.yml +++ b/share/oneprovision/ansible/packet.yml @@ -11,5 +11,14 @@ - opennebula-repository - opennebula-node-kvm - opennebula-ssh - - iptables + - role: iptables + iptables_base_rules_services: + - { protocol: 'tcp', port: 22 } + # TCP/179 bgpd (TODO: only needed on Route Refector(s)) + - { protocol: 'tcp', port: 179 } + # TCP/8742 default VXLAN port on Linux (UDP/4789 default IANA) + - { protocol: 'udp', port: 8472 } - update-replica + - role: frr + #bond0_0 is attached to the project private network + frr_iface: 'bond0_0' diff --git a/share/oneprovision/ansible/roles/frr/README.md b/share/oneprovision/ansible/roles/frr/README.md new file mode 100644 index 0000000000..7d0e1915ea --- /dev/null +++ b/share/oneprovision/ansible/roles/frr/README.md @@ -0,0 +1,16 @@ +# FRR + +## Description + +Installs FRR (https://frrouting.org/) and configured BGP EVPN extensions for VXLAN networks + +## Requirements + +To use this role you need to install netaddr Python library on the frontend, e.g.: pip install netaddr + +## Variables +All of the variables in this role are documented in the [defaults](defaults/main.yml) file. + +## Todo list + +None diff --git a/share/oneprovision/ansible/roles/frr/defaults/main.yml b/share/oneprovision/ansible/roles/frr/defaults/main.yml new file mode 100644 index 0000000000..0bfaaa62d7 --- /dev/null +++ b/share/oneprovision/ansible/roles/frr/defaults/main.yml @@ -0,0 +1,14 @@ +--- + +# frr-stable will be the latest official stable release +frr_frrver: 'frr-stable' + +# Number of route reflectors in the cluster +frr_rr_num: 1 + +# Network interface name to route VXLAN traffic +frr_iface: 'eth0' + +# The AS number used for BGP +frr_as: 65000 + diff --git a/share/oneprovision/ansible/roles/frr/tasks/centos.yml b/share/oneprovision/ansible/roles/frr/tasks/centos.yml new file mode 100644 index 0000000000..3c4630142b --- /dev/null +++ b/share/oneprovision/ansible/roles/frr/tasks/centos.yml @@ -0,0 +1,49 @@ +--- + +- name: Add FRR RPM repository + yum: + name: https://rpm.frrouting.org/repo/{{ frr_frrver }}-repo-1-0.el{{ ansible_distribution_major_version }}.noarch.rpm + state: present + disable_gpg_check: True + +- name: Install FRR + package: + name: frr + state: latest + register: pkg_result + until: pkg_result is succeeded + retries: 3 + delay: 10 + +- name: Install FRR Python Tools + package: + name: frr-pythontools + state: latest + register: pkg_result + until: pkg_result is succeeded + retries: 3 + delay: 10 + +- name: Configure BGP (RR) + template: + src: bgpd_rr.conf.j2 + dest: /etc/frr/bgpd.conf + when: vars['ansible_' + frr_iface].ipv4.address in rr_servers + +- name: Configure BGP + template: + src: bgpd.conf.j2 + dest: /etc/frr/bgpd.conf + when: not vars['ansible_' + frr_iface].ipv4.address in rr_servers + +- name: Enable BGP daemon + replace: + path: /etc/frr/daemons + regexp: '^bgpd=no' + replace: 'bgpd=yes' + +- name: Start FRR service + service: + name: frr + state: started + enabled: yes diff --git a/share/oneprovision/ansible/roles/frr/tasks/main.yml b/share/oneprovision/ansible/roles/frr/tasks/main.yml new file mode 100644 index 0000000000..1bb50d7807 --- /dev/null +++ b/share/oneprovision/ansible/roles/frr/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# +# Define network facts to generate BGP configuration +# - rr_servers (array with route reflectors IPs) +# - network_cidr (network address in CIDR format of BGP interface) +- name: Define cluster RRs + set_fact: + rr_servers : "{{ rr_servers|default([]) + [ hostvars[item]['ansible_' + frr_iface].ipv4.address ] }}" + with_items: "{{ groups['all'][:frr_rr_num] }}" + +- name: Define Network Mask + vars: + net_str: "{{ vars['ansible_' + frr_iface].ipv4.network \ + + '/' + vars['ansible_' + frr_iface].ipv4.netmask }}" + set_fact: + network_cidr: "{{ net_str | ipaddr('net') }}" + +- include: centos.yml + when: ansible_os_family == "RedHat" + +# - include: debian.yml +# when: ansible_os_family == "Debian" diff --git a/share/oneprovision/ansible/roles/frr/templates/bgpd.conf.j2 b/share/oneprovision/ansible/roles/frr/templates/bgpd.conf.j2 new file mode 100644 index 0000000000..20b3523276 --- /dev/null +++ b/share/oneprovision/ansible/roles/frr/templates/bgpd.conf.j2 @@ -0,0 +1,26 @@ +! +! Node configuration file +! +hostname {{ ansible_nodename }} +! +log file /var/log/frr/bgpd.log +! +router bgp {{ frr_as }} + bgp router-id {{ vars['ansible_' + frr_iface].ipv4.address }} + no bgp default ipv4-unicast + neighbor fabric peer-group + neighbor fabric remote-as {{ frr_as }} + neighbor fabric capability extended-nexthop + ! debug route reflector list: {{ rr_servers }} +{% for k in rr_servers %} +{% if k != vars['ansible_' + frr_iface].ipv4.address %} + neighbor {{ k }} peer-group fabric +{% endif %} +{% endfor %} + ! + address-family l2vpn evpn + neighbor fabric activate + advertise-all-vni + exit-address-family + ! +end diff --git a/share/oneprovision/ansible/roles/frr/templates/bgpd_rr.conf.j2 b/share/oneprovision/ansible/roles/frr/templates/bgpd_rr.conf.j2 new file mode 100644 index 0000000000..40fd01634e --- /dev/null +++ b/share/oneprovision/ansible/roles/frr/templates/bgpd_rr.conf.j2 @@ -0,0 +1,23 @@ +! +! Route Reflector configuration +! +hostname {{ ansible_nodename }} +! +log file /var/log/frr/bgpd.log +! +router bgp {{ frr_as }} + bgp router-id {{ vars['ansible_' + frr_iface].ipv4.address }} + bgp cluster-id {{ vars['ansible_' + frr_iface].ipv4.address }} + no bgp default ipv4-unicast + neighbor fabric peer-group + neighbor fabric remote-as {{ frr_as }} + neighbor fabric capability extended-nexthop + neighbor fabric update-source {{ vars['ansible_' + frr_iface].ipv4.address }} + bgp listen range {{ network_cidr }} peer-group fabric + address-family l2vpn evpn + neighbor fabric activate + neighbor fabric route-reflector-client + advertise-all-vni + exit-address-family + ! +end diff --git a/share/oneprovision/hybrid+/provisions/aws.d/networks.yml b/share/oneprovision/hybrid+/provisions/aws.d/networks.yml index daf5218683..2b2e42df4a 100644 --- a/share/oneprovision/hybrid+/provisions/aws.d/networks.yml +++ b/share/oneprovision/hybrid+/provisions/aws.d/networks.yml @@ -25,3 +25,9 @@ networks: packet_ip_type: 'public_ipv4' ipam_mad: 'aws' cidr: "${cluster.0.cidr}" + +vntemplates: + - name: "${provision}-private" + vn_mad: 'vxlan' + phydev: 'eth0' + automatic_vlan_id: 'yes' diff --git a/share/oneprovision/hybrid+/provisions/packet.d/networks.yml b/share/oneprovision/hybrid+/provisions/packet.d/networks.yml index 478adfab91..18c031c336 100644 --- a/share/oneprovision/hybrid+/provisions/packet.d/networks.yml +++ b/share/oneprovision/hybrid+/provisions/packet.d/networks.yml @@ -24,3 +24,9 @@ networks: size: '1' packet_ip_type: 'public_ipv4' ipam_mad: 'packet' + +vntemplates: + - name: "${provision}-private" + vn_mad: 'vxlan' + phydev: 'bond0' + automatic_vlan_id: 'yes' diff --git a/src/oneprovision/lib/terraform/providers/templates/aws/cluster.erb b/src/oneprovision/lib/terraform/providers/templates/aws/cluster.erb index d08b94789d..516b39fdc1 100644 --- a/src/oneprovision/lib/terraform/providers/templates/aws/cluster.erb +++ b/src/oneprovision/lib/terraform/providers/templates/aws/cluster.erb @@ -56,3 +56,53 @@ resource "aws_security_group" "device_<%= obj['ID'] %>_ssh" { } } +resource "aws_security_group" "device_<%= obj['ID'] %>_bgp" { + name = "allow_bgp" + description = "Allow BGP inbound traffic" + vpc_id = aws_vpc.device_<%= c['ID'] %>.id + + ingress { + description = "BGP from 10.0.0.0/16" + from_port = 179 + to_port = 179 + protocol = "tcp" + cidr_blocks = ["10.0.0.0/16"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "device_<%= obj['ID'] %>_bgp" + } +} + +resource "aws_security_group" "device_<%= obj['ID'] %>_vxlan" { + name = "allow_vxlan" + description = "Allow VXLAN inbound traffic" + vpc_id = aws_vpc.device_<%= c['ID'] %>.id + + ingress { + description = "VXLAN from 10.0.0.0/16" + from_port = 8472 + to_port = 8472 + protocol = "udp" + cidr_blocks = ["10.0.0.0/16"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "device_<%= obj['ID'] %>_vxlan" + } +} + diff --git a/src/oneprovision/lib/terraform/providers/templates/aws/host.erb b/src/oneprovision/lib/terraform/providers/templates/aws/host.erb index 18b56b04b7..53deebb7d7 100644 --- a/src/oneprovision/lib/terraform/providers/templates/aws/host.erb +++ b/src/oneprovision/lib/terraform/providers/templates/aws/host.erb @@ -2,7 +2,9 @@ resource "aws_instance" "device_<%= obj['ID'] %>" { ami = "<%= provision['AMI'] %>" instance_type = "<%= provision['INSTANCETYPE'] %>" - vpc_security_group_ids = [aws_security_group.device_<%= c['ID'] %>_ssh.id] + vpc_security_group_ids = [aws_security_group.device_<%= c['ID'] %>_ssh.id, + aws_security_group.device_<%= c['ID'] %>_bgp.id, + aws_security_group.device_<%= c['ID'] %>_vxlan.id] subnet_id = aws_subnet.device_<%= c['ID'] %>.id diff --git a/src/vn_template/VNTemplate.cc b/src/vn_template/VNTemplate.cc index 1c9ad47efb..6244b8e1d4 100644 --- a/src/vn_template/VNTemplate.cc +++ b/src/vn_template/VNTemplate.cc @@ -52,7 +52,7 @@ VNTemplate::VNTemplate(int id, int VNTemplate::insert(SqlDB *db, string& error_str) { - string vn_mad, phydev, bridge, auto_id_str, vlan_id, auto_outer_str, outer_id; + string vn_mad, phydev, bridge, vlan_id, outer_id; bool auto_id = false, auto_outer = false; int rc; @@ -70,20 +70,10 @@ int VNTemplate::insert(SqlDB *db, string& error_str) get_template_attribute("PHYDEV", phydev); get_template_attribute("BRIDGE", bridge); - get_template_attribute("AUTOMATIC_VLAN_ID", auto_id_str); - - if (auto_id_str == "YES") - { - auto_id = true; - } + get_template_attribute("AUTOMATIC_VLAN_ID", auto_id); get_template_attribute("VLAN_ID", vlan_id); - get_template_attribute("AUTOMATIC_OUTER_VLAN_ID", auto_outer_str); - - if (auto_outer_str == "YES") - { - auto_outer = true; - } + get_template_attribute("AUTOMATIC_OUTER_VLAN_ID", auto_outer); get_template_attribute("OUTER_VLAN_ID", outer_id);