Saturday, August 18, 2018

FreeRangeRouting(FRR) on Docker Container

FreeRangeRouting(FRR) on Docker Container

Topology

frr_docker_topology

Create a macvlan docker network


In this example I use the physical interface I’ve created SVI96

  • -d flag to use the macvlan Docker dirver
  • –subnet= my testing subnet is 198.18.62.0/24
  • –ip-range= the subset of the IP pool for docker to assign IP to container
  • –gateway= gateway for container to use
  • macvlanSVI96 name of the macvlan bridge
docker network create -d macvlan \
    --subnet=198.18.62.0/24 \
    --ip-range=198.18.62.120/29 \
    --gateway=198.18.62.1 \
    -o macvlan_mode=bridge \
    -o parent=SVI96 macvlanSVI96

Verify

[root@kvmhost02 ~]# docker network inspect macvlanSVI96
[
    {
        "Name": "macvlanSVI96",
        "Id": "bb185fe60be8dccbdfe53b4f0d03952a2298a752bd2aac25cffdd14490fb4690",
        "Created": "2018-08-16T20:05:01.088473083-05:00",
        "Scope": "local",
        "Driver": "macvlan",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "198.18.62.0/24",
                    "IPRange": "198.18.62.120/29",
                    "Gateway": "198.18.62.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "91a7e13fe4fbffa4695cfb77b43c2f2fb20f70d6145fefe851790bd6c0a54d42": {
                "Name": "ubuntu_frr01",
                "EndpointID": "fd2d4a88826344c95c6dc6f22f5678f6f67c017ad78afce7d981cf6dcdf6a723",
                "MacAddress": "02:42:c6:12:3e:7a",
                "IPv4Address": "198.18.62.122/24",
                "IPv6Address": ""
            },
            "a0447e8c05bcef7baf5ac49bffde53521ffbdce2f19ac6b9c16a0e7b7dd0396a": {
                "Name": "ubuntu_frr",
                "EndpointID": "91272b621a53d6888cbb9de126edeced7d524326c8eb9142471978530134ed7f",
                "MacAddress": "02:42:c6:12:3e:7b",
                "IPv4Address": "198.18.62.123/24",
                "IPv6Address": ""
            },
            "e799098ddc10f8007a8cde7dc8d14cd710efce8b414e7f99d70e94a8703d59cc": {
                "Name": "frr01",
                "EndpointID": "dac863b1ae4abbbaa9d96d5a7582c17d58eca135ac7301e5928f05ae4d59a2ce",
                "MacAddress": "02:42:c6:12:3e:79",
                "IPv4Address": "198.18.62.121/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "macvlan_mode": "bridge",
            "parent": "SVI96"
        },
        "Labels": {}
    }
]

Create a new ubuntu docker container

docker run -dit --net=macvlanSVI96 --name ubuntu_frr ubuntu

output:

[root@lab_host]# docker run -dit --net=macvlanSVI96 --name ubuntu_frr ubuntu
a0447e8c05bcef7baf5ac49bffde53521ffbdce2f19ac6b9c16a0e7b7dd0396a

run docker exec

docker exec -it ubuntu_frr /bin/bash

Ubuntu version used for this demo

root@a0447e8c05bc:/# cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.1 LTS"
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

Updatae

apt-get update

Add packages

apt-get install -y git autoconf automake libtool make gawk libreadline-dev texinfo 
apt-get install -y pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest
apt-get install -y libc-ares-dev python3-dev libsystemd-dev python-ipaddr python3-sphinx
apt-get install -y install-info net-tools iputils-ping wget mtr python2.7 python-pip  
apt-get install -y openssh-server vim sudo libffi-dev libssl-dev python-dev python-cffi
apt-get install -y libxslt1-dev python-pip protobuf-c-compiler libprotobuf-c-dev libzmq5 libzmq3-dev

Get FRR from git, complie/install it

add frr groups and user

sudo groupadd -r -g 92 frr
sudo groupadd -r -g 85 frrvty
sudo adduser --system --ingroup frr --home /var/run/frr/ \
   --gecos "FRR suite" --shell /sbin/nologin frr
sudo usermod -a -G frrvty frr

Download source

git clone https://github.com/frrouting/frr.git frr

Configure

cd frr
./bootstrap.sh
./configure \
    --prefix=/usr \
    --enable-exampledir=/usr/share/doc/frr/examples/ \
    --localstatedir=/var/run/frr \
    --sbindir=/usr/lib/frr \
    --sysconfdir=/etc/frr \
    --enable-pimd \
    --enable-watchfrr \
    --enable-ospfclient=yes \
    --enable-ospfapi=yes \
    --enable-multipath=64 \
    --enable-user=frr \
    --enable-group=frr \
    --enable-sharpd \
    --enable-vty-group=frrvty \
    --enable-configfile-mask=0640 \
    --enable-logfile-mask=0640 \
    --enable-rtadv \
    --enable-fpm \
    --enable-ldpd \
    --enable-staticd \
    --enable-systemd=yes \
    --enable-protobuf \
    --enable-zeromq \
    --with-pkg-git-version \
    --with-pkg-extra-version=-MyOwnFRRVersion

Compile

make
make check
sudo make install 

Create empty FRR configuration files

sudo mkdir /var/log/frr
sudo mkdir /etc/frr
sudo touch /etc/frr/zebra.conf
sudo touch /etc/frr/bgpd.conf
sudo touch /etc/frr/ospfd.conf
sudo touch /etc/frr/ospf6d.conf
sudo touch /etc/frr/isisd.conf
sudo touch /etc/frr/ripd.conf
sudo touch /etc/frr/ripngd.conf
sudo touch /etc/frr/pimd.conf
sudo touch /etc/frr/nhrpd.conf
sudo touch /etc/frr/eigrpd.conf
sudo touch /etc/frr/babeld.conf
sudo touch /etc/frr/sharpd.conf
sudo chown -R frr:frr /etc/frr/
sudo touch /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf

Monolithic configuration

sudo install -m 755 -o frr -g frr -d /var/log/frr
sudo install -m 775 -o frr -g frrvty -d /etc/frr
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/frr.conf

Apply Sysctl Values

vi /etc/sysctl.conf

# Enables IPv4/IPv6 Routing
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding=1

Apply

sysctl -p

Start FRR

/usr/lib/frr/frr start

Start daemons

NOTE: Additional daemon process is needed to run ospfd

/usr/lib/frr/ospfd -n 11 --daemon -A 127.0.0.1
-n 11 means the ospf process will be 11, EX:
configure terminal 
router ospf 11
/usr/lib/frr/zebra -s 90000000 --daemon -A 127.0.0.1
/usr/lib/frr/bgpd --daemon -A 127.0.0.1
/usr/lib/frr/ospfd --daemon -A 127.0.0.1
/usr/lib/frr/ospfd -n 11 --daemon -A 127.0.0.1
/usr/lib/frr/eigrpd --daemon -A 127.0.0.1
/usr/lib/frr/sharpd --daemon -A 127.0.0.1

Verification

root@e799098ddc10:/# vtysh

Hello, this is FRRouting (version 3.2+cl3u4).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

e799098ddc10# show run
Building configuration...

Current configuration:
!
frr version 3.2+cl3u4
frr defaults datacenter
hostname e799098ddc10
username cumulus nopassword
!
service integrated-vtysh-config
!
log syslog informational
!
interface lo1
 ip address 2.2.2.2/32
!
interface lo10
 ip address 78.78.78.78/32
!
router bgp 65001
 coalesce-time 1000
 neighbor 198.18.62.123 remote-as 65000
!
line vty
!
end

e799098ddc10# show bgp ipv4 unicast summary
BGP router identifier 198.18.62.121, local AS number 65001 vrf-id 0
BGP table version 1
RIB entries 1, using 152 bytes of memory
Peers 1, using 20 KiB of memory

Neighbor                    V         AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd
a0447e8c05bc(198.18.62.123) 4      65000     347     349        0    0    0 00:17:10            1

Total number of neighbors 1

e799098ddc10# show ip bgp
BGP table version is 1, local router ID is 198.18.62.121
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
              i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 1.1.1.1/32       198.18.62.123            0             0 65000 i

Displayed  1 routes and 1 total paths

Friday, July 20, 2018

Arista vEOS on KVM

Arista vEOS on KVM

Topology

veos_topology

Convert vEOS vmdk to qcow2

Download a copy of vEOS-lab HERE, however registered account is required.
Once the image(vEOS-lab-4.20.1F-combine.vmdk) is downloaded we can start converting it to qcow2

#qemu-img convert -o compat=1.1 -f vmdk -O qcow2 -c -p vEOS-lab-4.20.1F-combined.vmdk

Create a new OVS bridge

In this example I’m creating two OVS bridge called brMGMT & brLAB

[root@vhost1 ~]# ovs-vsctl add-br brMGMT
[root@vhost1 ~]# ovs-vsctl add-br brLAB

Verify

[root@vhost1 ~]# ovs-vsctl list-br
brLAB
brMGMT

Create a new vEOS instance

I ran the following virt-install command

NOTE:
I made a new copy of the image named vEOS01.qcow2 and associate the OVS bridges

virt-install \
--connect=qemu:///system \
--name=vEOS01 \
--os-type=linux \
--arch=x86_64 \
--cpu host-model \
--vcpus=1,sockets=1,cores=1,threads=1 \
--hvm \
--ram=2048 \
--disk path=/var/lib/libvirt/images/veos01.qcow2,bus=ide,size=8,sparse=false,cache=none,format=qcow2 \
--network bridge=brMGMT,model=e1000,target=virtualport_type=openvswitch \
--network bridge=brLAB,model=e1000,virtualport_type=openvswitch \
--boot hd \
--graphics none \
--console pty,target_type=serial \
-d

After virt-install completes, we should be able to see the vEOS01 is running

[root@vhost1 ~]# virsh list
 Id    Name                           State
----------------------------------------------------
 21    vEOS01                         running

Run virsh console command to console to the veos

[root@vhost1 ~]# virsh console vEOS01
Connected to domain vEOS01
Escape character is ^]

localhost login: admin
Password:
Last login: Wed Jul 11 16:22:19 on ttyS0
localhost>
localhost> enable
localhost#show interfaces status
Port       Name        Status       Vlan     Duplex Speed  Type            Flags
Et1                    connected    routed   full   unconf EbraTestPhyPort
Ma1                    connected    routed   a-full a-1G   10/100/1000

Additional setup and validation on the OVS

To check which vnet interface assigns to the vEOS

virsh dumpxml vEOS01

Since the default OVS port is in trunk mode and Arista Ma1 interface doesn’t support dot1q, we will need to tag the vlan id on the vEOS port belongs to OVS bridge brMGMT

[root@vhost1 ~]# virsh dumpxml vEOS01 | grep bridge -A 6
    <interface type='bridge'>
      <mac address='52:54:00:2b:ed:50'/>
      <source bridge='brMGMT'/>
      <virtualport type='openvswitch'>
        <parameters interfaceid='fd0c900a-01a1-4437-98a1-7bfac1e7687a'/>
      </virtualport>
      <target dev='vnet0'/>
      <model type='e1000'/>
      <alias name='net0'/>
--
    <interface type='bridge'>
      <mac address='52:54:00:b9:88:70'/>
      <source bridge='brLAB'/>
      <virtualport type='openvswitch'>
        <parameters interfaceid='4f98706d-33eb-4241-9853-ebcca447399d'/>
      </virtualport>
      <target dev='vnet1'/>
      <model type='e1000'/>
      <alias name='net1'/>

vnet0 and vnet1 are generated for the vEOS

To verify under the OVS

[root@vhost1 ~]# ovs-vsctl list-ifaces brMGMT
vnet0
[root@vhost1 ~]# ovs-vsctl list-ifaces brLAB
vnet1

Set vnet0 port (which is assigned to the ma1 on the vEOS) with a vlan tag

[root@vhost1 ~]# ovs-vsctl set port vnet0 tag=101

Verify it’s setup correctly

ovs-vsctl show 
    Bridge brMGMT
        Port brMGMT
            Interface brMGMT
                type: internal
        Port "vnet0"
            tag: 101
            Interface "vnet0"

To enable layer2 protocols like LLDP/SPT/LACP between the different vEOS thru the OVS, for example in our case it will be the brLAB bridge. This will allows two vEOS to setup LACP port-channels or/and MLAG.

[root@vhost1 ~]#ovs-vsctl set bridge brMGMT other-config:forward-bpdu=true