Skip to content

Commit

Permalink
mgmt_vrf_namespace: management vrf using namespace solution
Browse files Browse the repository at this point in the history
  • Loading branch information
kannankvs committed Jan 9, 2019
1 parent 1ffb34b commit 54af476
Show file tree
Hide file tree
Showing 11 changed files with 504 additions and 1 deletion.
12 changes: 12 additions & 0 deletions files/build_templates/sonic_debian_extension.j2
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,18 @@ sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostcfgd.service
sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/hostcfgd/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/

# Copy the management VRF related scripts
sudo cp $IMAGE_CONFIGS/interfaces/if_pre_up_netns $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/interfaces/if_up_netns $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/interfaces/if_down_netns $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/interfaces/create-mgmt-vrf-iptables.sh $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/interfaces/delete-mgmt-vrf-iptables.sh $FILESYSTEM_ROOT/usr/bin/

# Copy vrfcfgd files
sudo cp $IMAGE_CONFIGS/vrfcfgd/vrfcfgd.service $FILESYSTEM_ROOT/etc/systemd/system/
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable vrfcfgd.service
sudo cp $IMAGE_CONFIGS/vrfcfgd/vrfcfgd $FILESYSTEM_ROOT/usr/bin/

# Copy the buffer configuration template
sudo cp $BUILD_TEMPLATES/buffers_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/

Expand Down
27 changes: 27 additions & 0 deletions files/image_config/interfaces/create-mgmt-vrf-iptables.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin//bash

set -e

VRFNAME="mgmt"

ip netns exec $VRFNAME iptables -t nat -A PREROUTING -i eth0 -j $IF_MGMT_VRF_CHAIN

ip netns exec $VRFNAME iptables -t nat -A POSTROUTING -p tcp -o $IF_PEER_IFACE -j SNAT --to-source $IF_IF1_IP:62000-65000
ip netns exec $VRFNAME iptables -t nat -A POSTROUTING -p udp -o $IF_PEER_IFACE -j SNAT --to-source $IF_IF1_IP:62000-65000

ip netns exec $VRFNAME iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

ip netns exec $VRFNAME iptables -t nat -A $IF_MGMT_VRF_CHAIN -p tcp --dport 22 -j DNAT --to-destination $IF_IF2_IP

ip netns exec $VRFNAME iptables -t nat -A $IF_MGMT_VRF_CHAIN -p tcp --dport 20 -j DNAT --to-destination $IF_IF2_IP

ip netns exec $VRFNAME iptables -t nat -A $IF_MGMT_VRF_CHAIN -p tcp --dport 21 -j DNAT --to-destination $IF_IF2_IP

ip netns exec $VRFNAME iptables -t nat -A $IF_MGMT_VRF_CHAIN -p udp --dport 161 -j DNAT --to-destination $IF_IF2_IP

ip netns exec $VRFNAME iptables -t nat -A $IF_MGMT_VRF_CHAIN -p udp --dport 69 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME iptables -t nat -A $IF_MGMT_VRF_CHAIN -p tcp --dport 80 -j DNAT --to-destination $IF_IF2_IP

ip netns exec $VRFNAME iptables -t nat -A $IF_MGMT_VRF_CHAIN -p tcp --dport 443 -j DNAT --to-destination $IF_IF2_IP

32 changes: 32 additions & 0 deletions files/image_config/interfaces/delete-mgmt-vrf-iptables.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin//bash

set -e

VRFNAME="mgmt"

ip netns exec $VRFNAME iptables -t nat -D PREROUTING -i eth0 -j $IF_MGMT_VRF_CHAIN

ip netns exec $VRFNAME iptables -t nat -D POSTROUTING -p tcp -o ${IF_PEER_IFACE} -j SNAT --to-source ${IF_IF1_IP}:62000-65000
ip netns exec $VRFNAME iptables -t nat -D POSTROUTING -p udp -o ${IF_PEER_IFACE} -j SNAT --to-source ${IF_IF1_IP}:62000-65000

ip netns exec $VRFNAME iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

ip netns exec $VRFNAME iptables -t nat -D $IF_MGMT_VRF_CHAIN -p tcp --dport 22 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME iptables -t nat -D $IF_MGMT_VRF_CHAIN -p tcp --dport 20 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME iptables -t nat -D $IF_MGMT_VRF_CHAIN -p tcp --dport 21 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME iptables -t nat -D $IF_MGMT_VRF_CHAIN -p udp --dport 161 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME iptables -t nat -D $IF_MGMT_VRF_CHAIN -p udp --dport 69 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME iptables -t nat -D $IF_MGMT_VRF_CHAIN -p tcp --dport 80 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME iptables -t nat -D $IF_MGMT_VRF_CHAIN -p tcp --dport 443 -j DNAT --to-destination ${IF_IF2_IP}

ip netns exec $VRFNAME sysctl -w net.ipv4.conf.eth0.route_localnet=0

ip netns exec $VRFNAME sysctl -w net.ipv4.conf.${IF_PEER_IFACE}.route_localnet=0

sysctl -w net.ipv4.conf.${IFACE}.route_localnet=0
28 changes: 28 additions & 0 deletions files/image_config/interfaces/if_down_netns
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/sh

set -e

if [ -n "${IF_PEER_NETNS}" -a -n "${IF_PEER_IFACE}" ]
then
if OUTPUT=$(ip netns list | grep -w ${IF_PEER_NETNS})
then
# Take down the remote end of the veth
ip netns exec ${IF_PEER_NETNS} ip link set ${IF_PEER_IFACE} down

case "${IF_CONFIGURE_INTERFACES}" in
true|yes|on)
# Ifdown the interfaces inside the netns and inside
# a mount namespace with /run/network.nsname mounted
# on /run/network
unshare -m /bin/sh <<-EOF
mount --make-rprivate /
mount --bind /run/network.${IF_PEER_NETNS} /run/network
/usr/bin/delete-mgmt-vrf-iptables.sh
logger "if_down_netns: Doing ifdown for the interfaces present in management namespace."
ip netns exec ${IF_PEER_NETNS} ifdown -i /etc/network/interfaces.${IF_PEER_NETNS} -a
EOF
;;
esac
fi
fi
54 changes: 54 additions & 0 deletions files/image_config/interfaces/if_pre_up_netns
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/bin/sh
# filename:

set -e

if [ -n "${IF_PEER_NETNS}" -a -n "${IF_PEER_IFACE}" ]
then
logger "if_pre_up_netns: User is enabling management VRF. interfaces.j2 has set the required variables. Create the management namespace if not already present."
# Create netns if it doesn't already exist, and bring up the loopback
if ! OUTPUT=$(ip netns list | grep -w ${IF_PEER_NETNS})
then
logger "if_pre_up_netns: management vrf does not exist. Create it now."
mkdir -p /run/network.${IF_PEER_NETNS}
rm -rf /run/network.${IF_PEER_NETNS}/*
ip netns add ${IF_PEER_NETNS}
ip netns exec ${IF_PEER_NETNS} ip link set lo up
else
logger "if_pre_up_netns: management vrf already exists. No need to create it."
fi

if OUTPUT=$(ifconfig eth0)
then
logger "if_pre_up_netns: eth0 is in default VRF. Move it to management VRF"
# Move the management interface eth0 from default namespace to management namespace
ip link set dev eth0 netns ${IF_PEER_NETNS}
else
logger "if_pre_up_netns: eth0 is NOT in default VRF. No need to move it."
fi

# if veth pair is already existing, there will be a link by name if1@if2
if ! OUTPUT=$(ethtool -S if2)
then
logger "if_pre_up_netns: if1 & if2 are NOT in eth pair. Connect them via eth pair now"
# Add the veth pair for if2 with peer as if1
ip link add name ${IFACE} type veth peer name ${IF_PEER_IFACE}
else
logger "if_pre_up_netns: if1 & if2 are already in eth pair. NO need to connect them via eth pair now"
fi

# if if1 is already part of management namespace, nothing to do. Else move it to the management namespace
if ! OUTPUT=$(ip netns exec ${IF_PEER_NETNS} ifconfig if1)
then
logger "if_pre_up_netns: if1 is not in management VRF. Move it now"
# Put the remote end interface if1 into the netns
ip link set dev ${IF_PEER_IFACE} netns ${IF_PEER_NETNS}
else
logger "if_pre_up_netns: if1 is alerady in management VRF. no need to move it"
fi

# Set if2 as UP
logger "if_pre_up_netns: Bringing up the if2"
ip link set ${IFACE} up

fi
76 changes: 76 additions & 0 deletions files/image_config/interfaces/if_up_netns
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/sh
# filename:

set -e


if [ -n "${IF_PEER_NETNS}" -a -n "${IF_PEER_IFACE}" ]
then
logger "if_up_netns: User is enabling management VRF. interfaces.j2 has set the required variables. management namespace was already created and eth0 is already moved to management namespace in if_pre_up_netns."

# Bring up the remote end of the veth
ip netns exec ${IF_PEER_NETNS} ip link set ${IF_PEER_IFACE} up

case "${IF_CONFIGURE_INTERFACES}" in
true|yes|on)
logger "if_up_netns: Configuring the veth pair and internal IP addresses for the internal interfaces."
ip netns exec ${IF_PEER_NETNS} ifconfig ${IF_PEER_IFACE} ${IF_IF1_IP}/${IF_IF1_PREFIXLEN}
ifconfig ${IFACE} ${IF_IF2_IP}/${IF_IF2_PREFIXLEN}

# Ifup the interfaces in the netns and inside
# a mount namespace with /run/network.nsname mounted
# on /run/network
unshare -m /bin/sh <<-EOF
mount --make-rprivate /
mount --bind /run/network.${IF_PEER_NETNS} /run/network
logger "if_up_netns: Doing ifup for the interfaces present in management namespace."
ip netns exec ${IF_PEER_NETNS} ifup -i /etc/network/interfaces.${IF_PEER_NETNS} -a
EOF
;;
esac

logger "if_up_netns: flushing rules from MgmtVrfChain"
ip netns exec ${IF_PEER_NETNS} iptables -t nat -F ${IF_MGMT_VRF_CHAIN} >/dev/null 2>&1 || true
# In case if the MgmtVrfChain exists, creating it again will result in the script failing & exiting. Delete is before creating.
logger "if_up_netns: Deleting MgmtVrfChain before creating it"
ip netns exec ${IF_PEER_NETNS} iptables -t nat -X ${IF_MGMT_VRF_CHAIN} >/dev/null 2>&1 || true
logger "if_up_netns: Creating MgmtVrfChain in management VRF."
ip netns exec ${IF_PEER_NETNS} iptables -t nat -N ${IF_MGMT_VRF_CHAIN}
logger "if_up_netns: Creating iptables rules in management VRF into MgmtVrfChain"
/usr/bin/create-mgmt-vrf-iptables.sh

# When 127 NW is used, default NS does not reply for the ARP request sent from management NS when default NS
# loopback interface netmask is 255.0.0.0. Change it to 255.255.255.0 in both namespaces.

ifconfig lo 127.0.0.1 netmask 255.255.255.0
ip netns exec ${IF_PEER_NETNS} ifconfig lo 127.0.0.1 netmask 255.255.255.0

# route_localnet should be set to 1 to force the linux to route packets for IP addresses 127.100.100.x
logger "if_up_netns: Setting route_localnet for if2 in default VRF."
sysctl -w net.ipv4.conf.$IFACE.route_localnet=1

logger "if_up_netns: Setting route_localnet for all interfaces in management VRF."
ip netns exec ${IF_PEER_NETNS} sysctl -w net.ipv4.conf.all.route_localnet=1
fi

if [ $IFACE = "lo" ];
then
logger "if_up_netns: ifup for lo is executed."
EXIST=`ip address show lo | grep "127.0.0.1/8" | wc -l`
if [ $EXIST -eq 1 ]
then
logger "if_up_netns: 8 bit 127 address is there."
EXIST2=`ip address show lo | grep "127.0.0.1/24" | wc -l`
if [ $EXIST2 -eq 1 ]
then
logger "if_up_netns: 24 bit 127 address is also there."
logger "if_up_netns: ifup for lo is executed. Deleting the 8 bit address which is conflicting with 24 bit mask"
ip address del 127.0.0.1/8 dev lo
else
logger "if_up_netns: 24 bit 127 address is NOT there."
fi
else
logger "if_up_netns: ifup for lo is executed. 8 bit address doe not exist and hence nothing to delete"
fi
fi

61 changes: 60 additions & 1 deletion files/image_config/interfaces/interfaces-config.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,65 @@
#!/bin/bash

ifdown --force eth0
VRFNAME="mgmt"

vrfenabled=`/usr/bin/redis-cli -n 4 hget "MGMT_VRF_CONFIG|vrf_global" mgmtVrfEnabled`

if [ ! -f /var/run/netns/$VRFNAME ]
then
logger "interfaces-config: management vrf is not enabled. Bringing down eth0 in default VRF."
ifdown --force eth0
else
logger "interfaces-config: management vrf is enabled. Bringing down eth0 in management VRF."
ip netns exec $VRFNAME ifdown --force eth0

fi

sonic-cfggen -d -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces

if [ "$vrfenabled" == "true" ]
then

# Copy the respective netns file to the respective directories
logger "interfaces-config: vrfenabled is true. copying the netns scripts & generating interfaces.mgmt file"

cp /usr/bin/if_pre_up_netns /etc/network/if-pre-up.d/netns
cp /usr/bin/if_up_netns /etc/network/if-up.d/netns
cp /usr/bin/if_down_netns /etc/network/if-down.d/netns

# create management namespace interfaces file which contains the eth0 and
# other management namespace interfaces.

sonic-cfggen -d -t /usr/share/sonic/templates/interfaces_mgmt.j2 > /etc/network/interfaces.$VRFNAME


#Following "elif" condition will be exceuted in two conditions. 1. First time fresh boot when vrfenabled variable itself is not there. 2. vrfenabled variable exists, but the value is not true (which is nothing but vrf is disabled.)

elif [ -f /var/run/netns/$VRFNAME ]
then
logger "interfaces-config: vrfenabled flag is false. Removing netns files, deleting iptables from management vrf and deleting the management VRF"

if [ -f /etc/network/if-up.d/netns ]
then
rm /etc/network/if-up.d/netns
fi
if [ -f /etc/network/if-pre-up.d/netns ]
then
rm /etc/network/if-pre-up.d/netns
fi
if [ -f /etc/network/if-down.d/netns ]
then
rm /etc/network/if-down.d/netns
fi
if [ -f /etc/network/interfaces.$VRFNAME ]
then
rm /etc/network/interfaces.$VRFNAME
fi
logger "interfaces-config: Deleting the management VRF"
ip netns del $VRFNAME
fi

logger "interfaces-config: Adding usb0 interface for bfn platforms."

# Add usb0 interface for bfn platforms
platform=$(sonic-cfggen -H -v 'DEVICE_METADATA["localhost"]["platform"]')
if [[ "$platform" == "x86_64-accton_wedge100bf_32x-r0" || "$platform" == "x86_64-accton_wedge100bf_65x-r0" ]]; then
Expand All @@ -16,8 +72,11 @@ up ifconfig usb0 txqueuelen 64
EOF
fi

logger "interfaces-config: Killing dhcp client."
[ -f /var/run/dhclient.eth0.pid ] && kill `cat /var/run/dhclient.eth0.pid` && rm -f /var/run/dhclient.eth0.pid

logger "interfaces-config: Restarting networking service."
systemctl restart networking

logger "interfaces-config: Bringing down loopback interfaces and bringing it back to up."
ifdown lo && ifup lo
13 changes: 13 additions & 0 deletions files/image_config/interfaces/interfaces.j2
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ iface lo {{ 'inet' if prefix | ipv4 else 'inet6' }} static
{% endblock loopback %}
{% block mgmt_interface %}

{% if (MGMT_VRF_CONFIG) and (MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true") %}
auto if2
iface if2 inet manual
peer-netns mgmt
peer-iface if1
configure-interfaces yes
if1-ip 127.100.100.1
if1-prefixlen 24
if2-ip 127.100.100.2
if2-prefixlen 24
mgmt-vrf-chain MgmtVrfChain
{% else %}
# The management network interface
auto eth0
{% if MGMT_INTERFACE %}
Expand Down Expand Up @@ -46,5 +58,6 @@ iface eth0 {{ 'inet' if prefix | ipv4 else 'inet6' }} static
{% else %}
iface eth0 inet dhcp
{% endif %}
{% endif %}
#
{% endblock mgmt_interface %}
48 changes: 48 additions & 0 deletions files/image_config/interfaces/interfaces_mgmt.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
{% block banner %}
# =============== Managed by SONiC Config Engine DO NOT EDIT! ===============
# generated from /usr/share/sonic/templates/interfaces_mgmt.j2 using sonic-cfggen
# file: /etc/network/interfaces.management
#
{% endblock banner %}

{% block loopback %}
# The loopback network interface
auto lo
iface lo inet loopback
{% endblock loopback %}

{% block mgmt_interface %}

{% if MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true" %}
# The management network interface
auto eth0
{% if MGMT_INTERFACE %}
{% for (name, prefix) in MGMT_INTERFACE %}
iface eth0 {{ 'inet' if prefix | ipv4 else 'inet6' }} static
address {{ prefix | ip }}
netmask {{ prefix | netmask if prefix | ipv4 else prefix | prefixlen }}
########## management network policy routing rules
# management port up rules
up ip {{ '-4' if prefix | ipv4 else '-6' }} route add default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} dev eth0 table default
#up ip {{ '-4' if prefix | ipv4 else '-6' }} route add default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }}
up ip {{ '-4' if prefix | ipv4 else '-6' }} route add {{ prefix | network }}/{{ prefix | prefixlen }} dev eth0 table default
up ip {{ '-4' if prefix | ipv4 else '-6' }} rule add from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table default
{% for route in MGMT_INTERFACE[(name, prefix)]['forced_mgmt_routes'] %}
up ip rule add to {{ route }} table default
{% endfor %}
# management port down rules
down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} dev eth0 table default
down ip {{ '-4' if prefix | ipv4 else '-6' }} route delete {{ prefix | network }}/{{ prefix | prefixlen }} dev eth0 table default
down ip {{ '-4' if prefix | ipv4 else '-6' }} rule delete from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table default
{% for route in MGMT_INTERFACE[(name, prefix)]['forced_mgmt_routes'] %}
down ip rule delete to {{ route }} table default
{% endfor %}
{# TODO: COPP policy type rules #}
{% endfor %}
{% else %}
iface eth0 inet dhcp
{% endif %}
{% endif %}
#
{% endblock mgmt_interface %}
Loading

0 comments on commit 54af476

Please sign in to comment.