Test-IgmpProxy:
Merging new test scenarios , validation is in progress.
Change-Id: Ic7712981b8d0efc109caf555bc612e6e5cd322ec
diff --git a/src/test/igmpproxy/igmpproxyTest.py b/src/test/igmpproxy/igmpproxyTest.py
index bdf7748..db7765e 100644
--- a/src/test/igmpproxy/igmpproxyTest.py
+++ b/src/test/igmpproxy/igmpproxyTest.py
@@ -35,6 +35,7 @@
from scapy.all import *
from select import select as socket_select
import time, monotonic
+import requests
import os
import random
import threading
@@ -46,6 +47,9 @@
from Channels import IgmpChannel
from CordLogger import CordLogger
from CordTestConfig import setup_module, teardown_module
+from onosclidriver import OnosCliDriver
+from CordTestUtils import get_mac, get_controller
+from portmaps import g_subscriber_port_map
from CordTestUtils import log_test
log_test.setLevel('INFO')
@@ -92,12 +96,24 @@
PORT_TX_DEFAULT = 2
PORT_RX_DEFAULT = 1
max_packets = 100
+ MAX_PORTS = 100
app = 'org.opencord.igmpproxy'
+ cord_config_app = 'org.opencord.config'
+ test_path = os.path.dirname(os.path.realpath(__file__))
+ proxy_device_id = OnosCtrl.get_device_id()
+ controller = get_controller()
+ app_files = [os.path.join(test_path, '..', 'apps/cord-config-3.0-SNAPSHOT.oar'), os.path.join(test_path, '..', 'apps/olt-app-3.0-SNAPSHOT.oar'), os.path.join(test_path, '..', 'apps/mcast-1.3.0-SNAPSHOT.oar'), os.path.join(test_path, '..', 'apps/onos-app-igmpproxy-1.1.0-SNAPSHOT.oar')]
+ proxy_config_file = os.path.join(test_path, '..', 'igmpproxy/igmpproxyconfig.json')
olt_conf_file = os.getenv('OLT_CONFIG_FILE', os.path.join(os.path.dirname(os.path.realpath(__file__)), '../setup/olt_config.json'))
ROVER_TEST_TIMEOUT = 300 #3600*86
ROVER_TIMEOUT = (ROVER_TEST_TIMEOUT - 100)
ROVER_JOIN_TIMEOUT = 60
VOLTHA_ENABLED = bool(int(os.getenv('VOLTHA_ENABLED', 0)))
+ configs = {}
+ proxy_interfaces_last = ()
+ interface_to_mac_map = {}
+ host_ip_map = {}
+ MAX_PORTS = 100
@classmethod
def setUpClass(cls):
@@ -107,32 +123,206 @@
OnosCtrl.config_device_driver()
OnosCtrl.cord_olt_config(cls.olt)
time.sleep(2)
+ cls.uninstall_cord_config_app()
+ cls.install_igmpproxy()
+ cls.igmp_proxy_setup()
@classmethod
def tearDownClass(cls):
if cls.VOLTHA_ENABLED is False:
OnosCtrl.config_device_driver(driver = 'ovs')
+ #cls.igmp_proxy_cleanup()
def setUp(self):
''' Activate the igmp proxy app'''
- super(igmp_exchange, self).setUp()
- self.onos_ctrl = OnosCtrl(self.app)
- self.onos_ctrl.activate()
+ super(igmpproxy_exchange, self).setUp()
self.igmp_channel = IgmpChannel()
def tearDown(self):
- super(igmp_exchange, self).tearDown()
+ super(igmpproxy_exchange, self).tearDown()
- def onos_load_config(self, config):
- log_test.info('onos load config is %s'%config)
- status, code = OnosCtrl.config(config)
+ @classmethod
+ def uninstall_cord_config_app(cls):
+ log_test.info('Uninstalling org.opencord.config 1.2 version app')
+ OnosCtrl(cls.cord_config_app).deactivate()
+ OnosCtrl.uninstall_app(cls.cord_config_app, onos_ip = cls.controller)
+
+ @classmethod
+ def install_igmpproxy(cls):
+ for app in cls.app_files:
+ OnosCtrl.install_app(app, onos_ip = cls.controller)
+ OnosCtrl(app).activate()
+
+ @classmethod
+ def igmp_proxy_setup(cls):
+ did = OnosCtrl.get_device_id()
+ cls.proxy_device_id = did
+ cls.olt = OltConfig(olt_conf_file = cls.olt_conf_file)
+ cls.port_map, _ = cls.olt.olt_port_map()
+ log_test.info('port map is %s'%cls.port_map)
+ if cls.port_map:
+ ##Per subscriber, we use 1 relay port
+ try:
+ proxy_port = cls.port_map[cls.port_map['relay_ports'][0]]
+ except:
+ proxy_port = cls.port_map['uplink']
+ cls.proxy_interface_port = proxy_port
+ cls.proxy_interfaces = (cls.port_map[cls.proxy_interface_port],)
+ else:
+ cls.proxy_interface_port = 100
+ cls.proxy_interfaces = (g_subscriber_port_map[cls.proxy_interface_port],)
+ cls.proxy_interfaces_last = cls.proxy_interfaces
+ if cls.port_map:
+ ##generate a ip/mac client virtual interface config for onos
+ interface_list = []
+ for port in cls.port_map['ports']:
+ port_num = cls.port_map[port]
+ if port_num == cls.port_map['uplink']:
+ continue
+ ip = cls.get_host_ip(port_num)
+ mac = cls.get_mac(port)
+ interface_list.append((port_num, ip, mac))
+
+ #configure igmp proxy virtual interface
+ proxy_ip = cls.get_host_ip(interface_list[0][0])
+ proxy_mac = cls.get_mac(cls.port_map[cls.proxy_interface_port])
+ interface_list.append((cls.proxy_interface_port, proxy_ip, proxy_mac))
+ cls.onos_interface_load(interface_list)
+
+ @classmethod
+ def igmp_proxy_cleanup(cls):
+ #reset the ONOS port configuration back to default
+ for config in cls.configs.items():
+ OnosCtrl.delete(config)
+ # if cls.onos_restartable is True:
+ # log_test.info('Cleaning up dhcp relay config by restarting ONOS with default network cfg')
+ # return cord_test_onos_restart(config = {})
+
+ @classmethod
+ def onos_load_config(cls, config,json_file=False):
+ log_test.info('onos load config is %s'%config)
+ status, code = OnosCtrl.config(config,json_file=json_file)
if status is False:
log_test.info('JSON request returned status %d' %code)
assert_equal(status, True)
time.sleep(2)
+ @classmethod
+ def onos_interface_load(cls, interface_list):
+ interface_dict = { 'ports': {} }
+ for port_num, ip, mac in interface_list:
+ port_map = interface_dict['ports']
+ port = '{}/{}'.format(cls.proxy_device_id, port_num)
+ port_map[port] = { 'interfaces': [] }
+ interface_list = port_map[port]['interfaces']
+ interface_map = { 'ips' : [ '{}/{}'.format(ip, 24) ],
+ 'mac' : mac,
+ 'name': 'vir-{}'.format(port_num)
+ }
+ interface_list.append(interface_map)
+
+ #cls.onos_load_config(interface_dict)
+ cls.configs['interface_config'] = interface_dict
+
+ @classmethod
+ def onos_igmp_proxy_config_load(cls):
+ proxy_connect_point = '{}/{}'.format(cls.proxy_device_id, cls.proxy_interface_port)
+ #log_test.info('\nrelay interface port is %s'%cls.proxy_interface_port)
+ #log_test.info('\nrelay interface is %s'%cls.port_map[cls.proxy_interface_port])
+ #log_test.info('\nconnect point is %s'%proxy_connect_point)
+ #cls.onos_load_config(cls.proxy_config_file,json_file=True)
+ igmpproxy_dict = {'apps':{
+ 'org.opencord.igmpproxy':{
+ 'igmpproxy':
+ {'globalConnectPointMode': 'true',
+ 'globalConnectPoint': proxy_connect_point,
+ 'UnsolicitedTimeOut': '2',
+ 'MaxResp': '10',
+ 'KeepAliveInterval': '120',
+ 'KeepAliveCount': '3',
+ 'LastQueryInterval': '2',
+ 'LastQueryCount': '2',
+ 'FastLeave': 'false',
+ 'PeriodicQuery': 'true',
+ 'IgmpCos': '7',
+ 'withRAUpLink': 'true',
+ 'withRADownLink': 'true'
+ }
+ },
+ 'org.opencord.mcast':{
+ 'ingressVlan': '222',
+ 'egressVlan': '17'
+ }
+ }
+ }
+ device_dict = {'devices':{
+ cls.proxy_device_id: {
+ 'basic': {
+ 'driver': 'default'
+ },
+ 'accessDevice': {
+ 'uplink': '2',
+ 'vlan': '222',
+ 'defaultVlan': '1'
+ }
+ }
+ }
+ }
+ log_test.info('igmp proxy dict is %s'%igmpproxy_dict)
+ cls.onos_load_config(igmpproxy_dict)
+ cls.onos_load_config(device_dict)
+ cls.configs['relay_config'] = igmpproxy_dict
+ cls.configs['device_config'] = device_dict
+
+ @classmethod
+ def get_host_ip(cls, port):
+ if cls.host_ip_map.has_key(port):
+ return cls.host_ip_map[port]
+ cls.host_ip_map[port] = '192.168.1.{}'.format(port)
+ return cls.host_ip_map[port]
+
+ @classmethod
+ def host_load(cls, iface):
+ '''Have ONOS discover the hosts for dhcp-relay responses'''
+ port = g_subscriber_port_map[iface]
+ host = '173.17.1.{}'.format(port)
+ cmds = ( 'ifconfig {} 0'.format(iface),
+ 'ifconfig {0} {1}'.format(iface, host),
+ 'arping -I {0} {1} -c 2'.format(iface, host),)
+ #'ifconfig {} 0'.format(iface), )
+ for c in cmds:
+ log_test.info('host load config command %s'%c)
+ os.system(c)
+
+ @classmethod
+ def host_config_load(cls, host_config = None):
+ for host in host_config:
+ status, code = OnosCtrl.host_config(host)
+ if status is False:
+ log_test.info('JSON request returned status %d' %code)
+ assert_equal(status, True)
+
+ @classmethod
+ def generate_host_config(cls,ip,mac):
+ num = 0
+ hosts_dict = {}
+ hosts_list = [(ip,mac),]
+ for host, mac in hosts_list:
+ port = num + 1 if num < cls.MAX_PORTS - 1 else cls.MAX_PORTS - 1
+ hosts_dict[host] = {'mac':mac, 'vlan':'none', 'ipAddresses':[host], 'location':{ 'elementId' : '{}'.format(cls.proxy_device_id), 'port': port}}
+ num += 1
+ return hosts_dict.values()
+
+
+ @classmethod
+ def get_mac(cls, iface):
+ if cls.interface_to_mac_map.has_key(iface):
+ return cls.interface_to_mac_map[iface]
+ mac = get_mac(iface, pad = 0)
+ cls.interface_to_mac_map[iface] = mac
+ return mac
+
def onos_ssm_table_load(self, groups, src_list = ['1.2.3.4'],flag = False):
- return
ssm_dict = {'apps' : { 'org.opencord.igmpproxy' : { 'ssmTranslate' : [] } } }
ssm_xlate_list = ssm_dict['apps']['org.opencord.igmpproxy']['ssmTranslate']
if flag: #to maintain seperate group-source pair.
@@ -148,6 +338,7 @@
d['source'] = s or '0.0.0.0'
d['group'] = g
ssm_xlate_list.append(d)
+ log_test.info('onos ssm table config dictionary is %s'%ssm_dict)
self.onos_load_config(ssm_dict)
cord_port_map = {}
for g in groups:
@@ -235,6 +426,7 @@
ip_pkt = self.igmp_eth/self.igmp_ip
pkt = ip_pkt/igmp
IGMPv3.fixup(pkt)
+ log_test.info('sending igmp join packet %s'%pkt.show())
sendp(pkt, iface=iface)
if delay != 0:
time.sleep(delay)
@@ -280,10 +472,100 @@
if delay != 0:
time.sleep(delay)
+ def test_igmpproxy_app_installation(self):
+ #self.uninstall_cord_config_app()
+ #self.install_igmpproxy()
+ auth = ('karaf','karaf')
+ url = 'http://{}:8181/onos/v1/applications'.format(self.controller)
+ for file in self.app_files:
+ with open(file, 'rb') as payload:
+ res = requests.post(url,auth=auth,data=payload)
+ assert_equal(res.ok, True)
+
+ def test_igmpproxy_app_netcfg(self):
+ auth = ('karaf','karaf')
+ net_cfg_url = 'http://{}:8181/onos/v1/network/configuration/'.format(self.controller)
+ with open(self.proxy_config_file, 'rb') as payload:
+ res = requests.post(net_cfg_url,auth=auth,data=payload)
+ assert_equal(res.ok, True)
+
+ def test_igmpproxy_for_first_join(self,iface='veth0'):
+ group = ['224.9.8.7']
+ src = ['10.9.8.7']
+ self.onos_igmp_proxy_config_load()
+ self.onos_ssm_table_load(group,src_list=src)
+ self.success = False
+ def recv_task():
+ def igmp_recv_cb(pkt):
+ log_test.info('igmp packet received on proxy interface')
+ self.success = True
+ sniff(prn = igmp_recv_cb,lfilter = lambda p: IP in p and p[IP].proto == 2 and p[IP].dst==self.IP_DST, count=1,timeout = 5, iface=self.proxy_interfaces[0])
+ t = threading.Thread(target = recv_task)
+ t.start()
+ self.send_igmp_join(groups = group, src_list = src,record_type = IGMP_V3_GR_TYPE_INCLUDE,
+ iface = iface)
+ t.join()
+ assert_equal(self.success,True)
+ """
+ ############# Traffic Test
+ def recv_task():
+ def igmp_recv_cb(pkt):
+ log_test.info('igmp data traffic received on proxy interface')
+ self.success = False
+ sniff(prn = igmp_recv_cb,count=1,timeout = 5, iface=self.proxy_interfaces[0])
+ t = threading.Thread(target = recv_task)
+ t.start()
+ data = repr(monotonic.monotonic())
+ pkt2 = Ether(dst='01:00:5e:09:08:07')/IP(src='10.9.8.7',dst='224.9.8.7')/data
+ log_test.info('igmp data traffic packet is %s'%pkt2.show())
+ sendp(pkt2,iface='veth2',count=10)
+ t.join()
+ assert_equal(self.success,False)
+ """
+
+ def test_igmpproxy_for_two_joins(self,iface='veth0'):
+ groups = ['224.9.8.7','224.9.8.8']
+ src = ['10.9.8.7']
+ self.onos_igmp_proxy_config_load()
+ self.onos_ssm_table_load(groups,src_list=src)
+ def recv_task():
+ def igmp_recv_cb(pkt):
+ log_test.info('igmp packet received on proxy interface')
+ self.success = True
+ sniff(prn = igmp_recv_cb,lfilter = lambda p: IP in p and p[IP].proto == 2 and p[IP].dst==self.IP_DST, count=1,timeout = 5, iface=self.proxy_interfaces[0])
+ for group in groups:
+ self.success = False
+ t = threading.Thread(target = recv_task)
+ t.start()
+ self.send_igmp_join(groups = [group], src_list = src,record_type = IGMP_V3_GR_TYPE_INCLUDE,
+ iface = iface)
+ t.join()
+ assert_equal(self.success,True)
+
+ def test_igmpproxy_for_igmp_joins_on_non_proxy_interface(self,iface='veth0',non_proxy_iface='veth2'):
+ group = ['224.9.8.7']
+ src = ['10.9.8.7']
+ self.onos_igmp_proxy_config_load()
+ self.onos_ssm_table_load(group,src_list=src)
+ def recv_task():
+ def igmp_recv_cb(pkt):
+ log_test.info('igmp packet received on non-proxy interface')
+ self.success = True
+ sniff(prn = igmp_recv_cb,lfilter = lambda p: IP in p and p[IP].proto == 2 and p[IP].dst==self.IP_DST, count=1,timeout = 5, iface=non_proxy_iface)
+ self.success = False
+ t = threading.Thread(target = recv_task)
+ t.start()
+ self.send_igmp_join(groups = [group], src_list = src,record_type = IGMP_V3_GR_TYPE_INCLUDE,
+ iface = iface)
+ t.join()
+ assert_equal(self.success,False)
+
@deferred(timeout=MCAST_TRAFFIC_TIMEOUT+10)
def test_igmpproxy_with_join_and_verify_traffic(self):
- groups = [self.MGROUP1, self.MGROUP1]
- self.onos_ssm_table_load(groups)
+ #groups = [self.MGROUP1, self.MGROUP1]
+ groups = ["238.2.3.4"]
+ self.onos_igmp_proxy_config_load()
+ #self.onos_ssm_table_load(groups)
df = defer.Deferred()
igmpState = IGMPProxyTestState(groups = groups, df = df)
igmpStateRecv = IGMPProxyTestState(groups = groups, df = df)