Adding a double tagged host in trellis.py
Updating the vagrant file to upgrande linux kernel to 4.15
and install ovs 2.9.2

Change-Id: Ic14f3d79fe65bca07960070f2b6e6151b33e5b7b
diff --git a/trellis/Vagrantfile b/trellis/Vagrantfile
index a46672e..0c04e17 100644
--- a/trellis/Vagrantfile
+++ b/trellis/Vagrantfile
@@ -1,9 +1,21 @@
 # -*- mode: ruby -*-
 # vi: set ft=ruby :
 
+required_plugins = %w(vagrant-reload vagrant-vbguest)
+
+plugins_to_install = required_plugins.select { |plugin| not Vagrant.has_plugin? plugin }
+if not plugins_to_install.empty?
+  puts "Installing plugins: #{plugins_to_install.join(' ')}"
+  if system "vagrant plugin install #{plugins_to_install.join(' ')}"
+    exec "vagrant #{ARGV.join(' ')}"
+  else
+    abort "Installation of one or more plugins has failed. Aborting."
+  end
+end
+
 Vagrant.configure("2") do |config|
   config.vm.box = "ubuntu/xenial64"
-  config.vm.box_version = "20171221.0.0"
+  config.vm.box_version = "20180717.0.0"
   config.vm.hostname = 'trellis-example'
   config.ssh.forward_agent = true
   config.ssh.forward_x11 = true
@@ -32,7 +44,32 @@
     git clone https://gerrit.onosproject.org/routing
 
     sudo ldconfig
-    SHELL
+
+    mkdir 4.15 && cd 4.15
+    wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.15/linux-headers-4.15.0-041500_4.15.0-041500.201802011154_all.deb
+    wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.15/linux-headers-4.15.0-041500-generic_4.15.0-041500.201802011154_amd64.deb
+    wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.15/linux-image-4.15.0-041500-generic_4.15.0-041500.201802011154_amd64.deb
+    sudo dpkg -i *.deb
+  SHELL
+
+  config.vm.provision :reload
+
+  config.vm.provision "shell", privileged: true, inline: <<-SHELL
+    /etc/init.d/openvswitch-switch stop
+    cd /tmp
+    wget http://openvswitch.org/releases/openvswitch-2.9.2.tar.gz
+    tar zxvf openvswitch-2.9.2.tar.gz
+    cd openvswitch-2.9.2
+    ./configure --prefix=/usr --with-linux=/lib/modules/`uname -r`/build
+    make
+    make install
+    make modules_install
+    rmmod openvswitch
+    depmod -a
+    /etc/init.d/openvswitch-switch start
+    rm -rf /tmp/openvswitch-2.9.2*
+    ovs-vsctl set Open_vSwitch . other_config:vlan-limit=2
+  SHELL
 
   config.vm.provider :virtualbox do |v|
       v.customize ["modifyvm", :id, "--cpus", 2]
diff --git a/trellis/trellis.json b/trellis/trellis.json
index e0aa174..cb945ea 100644
--- a/trellis/trellis.json
+++ b/trellis/trellis.json
@@ -19,12 +19,19 @@
         "of:0000000000000204/5" : {
             "interfaces" : [
                 {
+                    "ips" : [ "10.0.2.254/24" ]
+                }
+            ]
+        },
+        "of:0000000000000204/6" : {
+            "interfaces" : [
+                {
                     "ips" : [ "2000::2ff/120" ],
                     "vlan-untagged": 40
                 }
             ]
         },
-        "of:0000000000000204/6" : {
+        "of:0000000000000204/7" : {
             "interfaces" : [
                 {
                     "ips" : [ "2000::2ff/120" ],
diff --git a/trellis/trellis.py b/trellis/trellis.py
index 7208aa4..29ce684 100755
--- a/trellis/trellis.py
+++ b/trellis/trellis.py
@@ -1,6 +1,8 @@
 #!/usr/bin/python
 
 import sys
+from time import sleep
+
 sys.path.append('..')
 from mininet.topo import Topo
 from mininet.net import Mininet
@@ -11,7 +13,7 @@
 from ipaddress import ip_network
 from routinglib import BgpRouter
 from routinglib import RoutedHost, RoutedHost6
-from trellislib import DhcpClient, Dhcp6Client, DhcpRelay, DhcpServer, Dhcp6Server
+from trellislib import DhcpClient, Dhcp6Client, DhcpRelay, DhcpServer, Dhcp6Server, DoubleTaggedRoutedHost
 from trellislib import get_mininet, parse_trellis_args, set_up_zebra_config
 from functools import partial
 
@@ -42,10 +44,12 @@
         h2 = self.addHost('h2', cls=DhcpClient, mac='00:aa:00:00:00:02')
         h3 = self.addHost('h3', cls=DhcpClient, mac='00:aa:00:00:00:03')
         h4 = self.addHost('h4', cls=DhcpClient, mac='00:aa:00:00:00:04')
+        dth5 = self.addHost('dth5', cls=DoubleTaggedRoutedHost, mac='00:aa:00:00:00:05', ips=['10.0.2.3/24'], gateway='10.0.2.254', outerVlan=100, innerVlan=200)
         self.addLink(h1, s204)
         self.addLink(h2, s204)
         self.addLink(h3, s205)
         self.addLink(h4, s205)
+        self.addLink(dth5, s204)
 
         # IPv6 Hosts
         h1v6 = self.addHost('h1v6', cls=Dhcp6Client, mac='00:bb:00:00:00:01')
@@ -116,5 +120,8 @@
     net = get_mininet(arguments, topo, switch)
 
     net.start()
+    sleep(3)
+    print 'ping %s' % net.get('h1').IP()
+    net.get('dth5').cmd('ping -c 1 %s'% net.get('h1').IP())
     CLI(net)
     net.stop()
diff --git a/trellis/trellislib.py b/trellis/trellislib.py
index 6199f62..acb8e8f 100644
--- a/trellis/trellislib.py
+++ b/trellis/trellislib.py
@@ -38,6 +38,37 @@
         self.cmd('ip link remove link %s' % self.vlanIntf)
         super(TaggedRoutedHost, self).terminate()
 
+class DoubleTaggedRoutedHost(RoutedHost):
+    def __init__(self, name, ips, outerVlan, innerVlan, gateway, *args, **kwargs):
+        super(RoutedHost, self).__init__(name, *args, **kwargs)
+        self.ips = ips
+        self.gateway = gateway
+        self.innerVlan = innerVlan
+        self.outerVlan = outerVlan
+        self.innerVlanIntf = None
+        self.outerVlanIntf = None
+
+    def config(self, **kwargs):
+        Host.config(self, **kwargs)
+        self.outerVlanIntf = "%s.%s" % (self.defaultIntf(), self.outerVlan)
+        self.outerVlanIntf = self.outerVlanIntf.split("-")[1]
+        self.innerVlanIntf = "%s.%s" % (self.outerVlanIntf, self.innerVlan)
+        self.cmd('ip -4 addr flush dev %s' % self.defaultIntf())
+        self.cmd('ip link add link %s %s type vlan proto 802.1ad id %s' % (self.defaultIntf(), self.outerVlanIntf, self.outerVlan))
+        self.cmd('ip link add link %s %s type vlan proto 802.1Q id %s' % (self.outerVlanIntf, self.innerVlanIntf, self.innerVlan))
+        self.cmd('ip link set up %s' % self.outerVlanIntf)
+        self.cmd('ip link set up %s' % self.innerVlanIntf)
+
+        for ip in self.ips:
+            self.cmd('ip addr add %s dev %s' % (ip, self.innerVlanIntf))
+
+        self.cmd('ip route add default via %s' % self.gateway)
+
+    def terminate(self, **kwargs):
+        self.cmd('ip link remove link %s' % self.outerVlanIntf)
+        self.cmd('ip link remove link %s' % self.innerVlanIntf)
+        super(DoubleTaggedRoutedHost, self).terminate()
+
 class DhcpClient(Host):
     def __init__(self, name, *args, **kwargs):
         super(DhcpClient, self).__init__(name, **kwargs)