| |
| # Copyright 2017-present Open Networking Foundation |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| |
| import unittest |
| from twisted.internet import defer |
| from nose.tools import * |
| from IGMP import * |
| from ACL import ACLTest |
| from DHCP import DHCPTest |
| from Channels import Channels, IgmpChannel |
| from subscriberDb import SubscriberDB |
| import time, monotonic |
| from CordTestUtils import get_mac, log_test |
| from OltConfig import OltConfig |
| from OnosCtrl import OnosCtrl |
| from OnosFlowCtrl import OnosFlowCtrl |
| from CordContainer import Container, Onos, Quagga |
| from onosclidriver import OnosCliDriver |
| from CordTestServer import CordTestServer, cord_test_onos_restart, cord_test_quagga_restart,cord_test_quagga_stop, cord_test_quagga_shell,cord_test_shell |
| from portmaps import g_subscriber_port_map |
| import time, monotonic |
| from scapy_ssl_tls.ssl_tls import * |
| from scapy_ssl_tls.ssl_tls_crypto import * |
| import os |
| import json |
| from socket import socket |
| import pexpect |
| from Stats import Stats |
| import logging |
| logging.getLogger('scapy.runtime').setLevel(logging.ERROR) |
| from scapy.all import * |
| from OnosFlowCtrl import OnosFlowCtrl |
| from nose.twistedtools import reactor, deferred |
| import tempfile |
| import threading |
| from threading import current_thread |
| from threadPool import ThreadPool |
| import random |
| import collections |
| import requests |
| log_test.setLevel('INFO') |
| class cluster_igmp(object): |
| V_INF1 = 'veth0' |
| V_INF2 = 'veth1' |
| MGROUP1 = '239.1.2.3' |
| MGROUP2 = '239.2.2.3' |
| MINVALIDGROUP1 = '255.255.255.255' |
| MINVALIDGROUP2 = '239.255.255.255' |
| MMACGROUP1 = "01:00:5e:01:02:03" |
| MMACGROUP2 = "01:00:5e:02:02:03" |
| IGMP_DST_MAC = "01:00:5e:00:00:16" |
| IGMP_SRC_MAC = "5a:e1:ac:ec:4d:a1" |
| IP_SRC = '1.2.3.4' |
| IP_DST = '224.0.0.22' |
| NEGATIVE_TRAFFIC_STATUS = 1 |
| igmp_eth = Ether(dst = IGMP_DST_MAC, type = ETH_P_IP) |
| igmp_ip = IP(dst = IP_DST) |
| IGMP_TEST_TIMEOUT = 5 |
| IGMP_QUERY_TIMEOUT = 60 |
| MCAST_TRAFFIC_TIMEOUT = 10 |
| PORT_TX_DEFAULT = 2 |
| PORT_RX_DEFAULT = 1 |
| max_packets = 100 |
| app = 'org.opencord.igmp' |
| 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 |
| |
| @classmethod |
| def setUpClass(cls,controller=None): |
| cls.olt = OltConfig(olt_conf_file = cls.olt_conf_file) |
| cls.port_map, _ = cls.olt.olt_port_map() |
| OnosCtrl.cord_olt_config(cls.olt, controller=controller) |
| |
| @classmethod |
| def tearDownClass(cls): pass |
| |
| def setUp(self,controller=None): |
| self.setUpClass(controller=controller) |
| self.get_igmp_intf() |
| ''' Activate the igmp app''' |
| self.onos_ctrl = OnosCtrl(self.app,controller=controller) |
| self.onos_ctrl.activate() |
| self.igmp_channel = IgmpChannel(controller=controller) |
| |
| def tearDown(self): pass |
| |
| def onos_load_config(self, config,controller=None): |
| log_test.info('onos load config is %s'%config) |
| status, code = OnosCtrl(self.app).config(config,controller=controller) |
| if status is False: |
| log_test.info('JSON request returned status %d' %code) |
| assert_equal(status, True) |
| time.sleep(2) |
| |
| def onos_ssm_table_load(self, groups, src_list = ['1.2.3.4'],controller=None,flag = False): |
| ssm_dict = {'apps' : { 'org.onosproject.igmp' : { 'ssmTranslate' : [] } } } |
| ssm_xlate_list = ssm_dict['apps']['org.onosproject.igmp']['ssmTranslate'] |
| if flag: #to maintain seperate group-source pair. |
| for i in range(len(groups)): |
| d = {} |
| d['source'] = src_list[i] or '0.0.0.0' |
| d['group'] = groups[i] |
| ssm_xlate_list.append(d) |
| else: |
| for g in groups: |
| for s in src_list: |
| d = {} |
| d['source'] = s or '0.0.0.0' |
| d['group'] = g |
| ssm_xlate_list.append(d) |
| self.onos_load_config(ssm_dict,controller=controller) |
| cord_port_map = {} |
| for g in groups: |
| cord_port_map[g] = (self.PORT_TX_DEFAULT, self.PORT_RX_DEFAULT) |
| self.igmp_channel.cord_port_table_load(cord_port_map) |
| time.sleep(2) |
| |
| def mcast_ip_range(self,start_ip = '224.0.1.0', end_ip = '224.0.1.100'): |
| start = list(map(int, start_ip.split("."))) |
| end = list(map(int, end_ip.split("."))) |
| temp = start |
| ip_range = [] |
| ip_range.append(start_ip) |
| while temp != end: |
| start[3] += 1 |
| for i in (3, 2, 1): |
| if temp[i] == 255: |
| temp[i] = 0 |
| temp[i-1] += 1 |
| ip_range.append(".".join(map(str, temp))) |
| return ip_range |
| |
| def random_mcast_ip(self,start_ip = '224.0.1.0', end_ip = '224.0.1.100'): |
| start = list(map(int, start_ip.split("."))) |
| end = list(map(int, end_ip.split("."))) |
| temp = start |
| ip_range = [] |
| ip_range.append(start_ip) |
| while temp != end: |
| start[3] += 1 |
| for i in (3, 2, 1): |
| if temp[i] == 255: |
| temp[i] = 0 |
| temp[i-1] += 1 |
| ip_range.append(".".join(map(str, temp))) |
| return random.choice(ip_range) |
| |
| def source_ip_range(self,start_ip = '10.10.0.1', end_ip = '10.10.0.100'): |
| start = list(map(int, start_ip.split("."))) |
| end = list(map(int, end_ip.split("."))) |
| temp = start |
| ip_range = [] |
| ip_range.append(start_ip) |
| while temp != end: |
| start[3] += 1 |
| for i in (3, 2, 1): |
| if temp[i] == 255: |
| temp[i] = 0 |
| temp[i-1] += 1 |
| ip_range.append(".".join(map(str, temp))) |
| return ip_range |
| def iptomac(self, mcast_ip): |
| mcast_mac = '01:00:5e:' |
| octets = mcast_ip.split('.') |
| second_oct = int(octets[1]) & 127 |
| third_oct = int(octets[2]) |
| fourth_oct = int(octets[3]) |
| mcast_mac = mcast_mac + format(second_oct,'02x') + ':' + format(third_oct, '02x') + ':' + format(fourth_oct, '02x') |
| return mcast_mac |
| |
| def randomsourceip(self,start_ip = '10.10.0.1', end_ip = '10.10.0.100'): |
| start = list(map(int, start_ip.split("."))) |
| end = list(map(int, end_ip.split("."))) |
| temp = start |
| ip_range = [] |
| ip_range.append(start_ip) |
| while temp != end: |
| start[3] += 1 |
| for i in (3, 2, 1): |
| if temp[i] == 255: |
| temp[i] = 0 |
| temp[i-1] += 1 |
| ip_range.append(".".join(map(str, temp))) |
| return random.choice(ip_range) |
| |
| def get_igmp_intf(self): |
| inst = os.getenv('TEST_INSTANCE', None) |
| if not inst: |
| return 'veth0' |
| inst = int(inst) + 1 |
| if inst >= self.port_map['uplink']: |
| inst += 1 |
| if self.port_map.has_key(inst): |
| return self.port_map[inst] |
| return 'veth0' |
| |
| def igmp_verify_join(self, igmpStateList): |
| sendState, recvState = igmpStateList |
| ## check if the send is received for the groups |
| for g in sendState.groups: |
| tx_stats = sendState.group_map[g][0] |
| tx = tx_stats.count |
| assert_greater(tx, 0) |
| rx_stats = recvState.group_map[g][1] |
| rx = rx_stats.count |
| assert_greater(rx, 0) |
| log_test.info('Receive stats %s for group %s' %(rx_stats, g)) |
| |
| log_test.info('IGMP test verification success') |
| |
| def igmp_verify_leave(self, igmpStateList, leave_groups): |
| sendState, recvState = igmpStateList[0], igmpStateList[1] |
| ## check if the send is received for the groups |
| for g in sendState.groups: |
| tx_stats = sendState.group_map[g][0] |
| rx_stats = recvState.group_map[g][1] |
| tx = tx_stats.count |
| rx = rx_stats.count |
| assert_greater(tx, 0) |
| if g not in leave_groups: |
| log_test.info('Received %d packets for group %s' %(rx, g)) |
| for g in leave_groups: |
| rx = recvState.group_map[g][1].count |
| assert_equal(rx, 0) |
| |
| log_test.info('IGMP test verification success') |
| |
| def mcast_traffic_timer(self): |
| self.mcastTraffic.stopReceives() |
| |
| def send_mcast_cb(self, send_state): |
| for g in send_state.groups: |
| send_state.update(g, tx = 1) |
| return 0 |
| |
| ##Runs in the context of twisted reactor thread |
| def igmp_recv(self, igmpState, iface = 'veth0'): |
| p = self.recv_socket.recv() |
| try: |
| send_time = float(p.payload.load) |
| recv_time = monotonic.monotonic() |
| except: |
| log_test.info('Unexpected Payload received: %s' %p.payload.load) |
| return 0 |
| #log_test.info( 'Recv in %.6f secs' %(recv_time - send_time)) |
| igmpState.update(p.dst, rx = 1, t = recv_time - send_time) |
| return 0 |
| |
| def send_igmp_join(self, groups, src_list = ['1.2.3.4'], record_type=IGMP_V3_GR_TYPE_INCLUDE, |
| ip_pkt = None, iface = 'veth0', ssm_load = False, delay = 1): |
| if ssm_load is True: |
| self.onos_ssm_table_load(groups, src_list) |
| igmp = IGMPv3(type = IGMP_TYPE_V3_MEMBERSHIP_REPORT, max_resp_code=30, |
| gaddr=self.IP_DST) |
| for g in groups: |
| gr = IGMPv3gr(rtype= record_type, mcaddr=g) |
| gr.sources = src_list |
| igmp.grps.append(gr) |
| if ip_pkt is None: |
| ip_pkt = self.igmp_eth/self.igmp_ip |
| pkt = ip_pkt/igmp |
| IGMPv3.fixup(pkt) |
| sendp(pkt, iface=iface) |
| log_test.info('igmp join packet is %s'%pkt.show()) |
| if delay != 0: |
| time.sleep(delay) |
| |
| class cluster_tls(): |
| eap_app = 'org.opencord.aaa' |
| CLIENT_CERT_INVALID = '''-----BEGIN CERTIFICATE----- |
| MIIEyTCCA7GgAwIBAgIJAM6l2jUG56pLMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD |
| VQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNvbWV3aGVyZTETMBEGA1UE |
| ChMKQ2llbmEgSW5jLjEeMBwGCSqGSIb3DQEJARYPYWRtaW5AY2llbmEuY29tMSYw |
| JAYDVQQDEx1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjAzMTEx |
| ODUzMzVaFw0xNzAzMDYxODUzMzVaMIGLMQswCQYDVQQGEwJVUzELMAkGA1UECBMC |
| Q0ExEjAQBgNVBAcTCVNvbWV3aGVyZTETMBEGA1UEChMKQ2llbmEgSW5jLjEeMBwG |
| CSqGSIb3DQEJARYPYWRtaW5AY2llbmEuY29tMSYwJAYDVQQDEx1FeGFtcGxlIENl |
| cnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC |
| ggEBAL9Jv54TkqycL3U2Fdd/y5NXdnPVXwAVV3m6I3eIffVCv8eS+mwlbl9dnbjo |
| qqlGEgA3sEg5HtnKoW81l3PSyV/YaqzUzbcpDlgWlbNkFQ3nVxh61gSU34Fc4h/W |
| plSvCkwGSbV5udLtEe6S9IflP2Fu/eXa9vmUtoPqDk66p9U/nWVf2H1GJy7XanWg |
| wke+HpQvbzoSfPJS0e5Rm9KErrzaIkJpqt7soW+OjVJitUax7h45RYY1HHHlbMQ0 |
| ndWW8UDsCxFQO6d7nsijCzY69Y8HarH4mbVtqhg3KJevxD9UMRy6gdtPMDZLah1c |
| LHRu14ucOK4aF8oICOgtcD06auUCAwEAAaOCASwwggEoMB0GA1UdDgQWBBQwEs0m |
| c8HARTVp21wtiwgav5biqjCBwAYDVR0jBIG4MIG1gBQwEs0mc8HARTVp21wtiwga |
| v5biqqGBkaSBjjCBizELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQH |
| EwlTb21ld2hlcmUxEzARBgNVBAoTCkNpZW5hIEluYy4xHjAcBgkqhkiG9w0BCQEW |
| D2FkbWluQGNpZW5hLmNvbTEmMCQGA1UEAxMdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBB |
| dXRob3JpdHmCCQDOpdo1BueqSzAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6Ap |
| oCeGJWh0dHA6Ly93d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZI |
| hvcNAQELBQADggEBAK+fyAFO8CbH35P5mOX+5wf7+AeC+5pwaFcoCV0zlfwniANp |
| jISgcIX9rcetLxeYRAO5com3+qLdd9dGVNL0kwufH4QhlSPErG7OLHHAs4JWVhUo |
| bH3lK9lgFVlnCDBtQhslzqScR64SCicWcQEjv3ZMZsJwYLvl8unSaKz4+LVPeJ2L |
| opCpmZw/V/S2NhBbe3QjTiRPmDev2gbaO4GCfi/6sCDU7UO3o8KryrkeeMIiFIej |
| gfwn9fovmpeqCEyupy2JNNUTJibEuFknwx7JAX+htPL27nEgwV1FYtwI3qLiZqkM |
| 729wo9cFSslJNZBu+GsBP5LszQSuvNTDWytV+qY= |
| -----END CERTIFICATE-----''' |
| def __init__(self): |
| pass |
| def setUp(self,controller=None): |
| self.onos_ctrl = OnosCtrl(self.eap_app,controller=controller) |
| self.onos_aaa_config(controller=controller) |
| |
| def onos_aaa_config(self,controller=None): |
| log_test.info('controller in onos_aaa_config is %s'%controller) |
| aaa_dict = {'apps' : { 'org.opencord.aaa' : { 'AAA' : { 'radiusSecret': 'radius_password', |
| 'radiusIp': '172.17.0.2' } } } } |
| radius_ip = os.getenv('ONOS_AAA_IP') or '172.17.0.2' |
| aaa_dict['apps']['org.opencord.aaa']['AAA']['radiusIp'] = radius_ip |
| self.onos_ctrl.activate() |
| time.sleep(2) |
| self.onos_load_config(aaa_dict,controller=controller) |
| |
| def onos_load_config(self, config,controller=None): |
| log_test.info('controller in onos_load_config is %s'%controller) |
| log_test.info('onos load config is %s'%config) |
| status, code = OnosCtrl(self.eap_app).config(config,controller=controller) |
| if status is False: |
| log_test.info('JSON request returned status %d' %code) |
| assert_equal(status, True) |
| time.sleep(2) |
| |
| |
| class cluster_flows(): |
| |
| PORT_TX_DEFAULT = 2 |
| PORT_RX_DEFAULT = 1 |
| INTF_TX_DEFAULT = 'veth2' |
| INTF_RX_DEFAULT = 'veth0' |
| default_port_map = { |
| PORT_TX_DEFAULT : INTF_TX_DEFAULT, |
| PORT_RX_DEFAULT : INTF_RX_DEFAULT, |
| INTF_TX_DEFAULT : PORT_TX_DEFAULT, |
| INTF_RX_DEFAULT : PORT_RX_DEFAULT |
| } |
| app = 'org.onosproject.cli' |
| |
| def incmac(self, mac): |
| tmp = str(hex(int('0x'+mac,16)+1).split('x')[1]) |
| mac = '0'+ tmp if len(tmp) < 2 else tmp |
| return mac |
| |
| def next_mac(self, mac): |
| mac = mac.split(":") |
| mac[5] = self.incmac(mac[5]) |
| |
| if len(mac[5]) > 2: |
| mac[0] = self.incmac(mac[0]) |
| mac[5] = '01' |
| |
| if len(mac[0]) > 2: |
| mac[0] = '01' |
| mac[1] = self.incmac(mac[1]) |
| mac[5] = '01' |
| return ':'.join(mac) |
| |
| def to_egress_mac(cls, mac): |
| mac = mac.split(":") |
| mac[4] = '01' |
| |
| return ':'.join(mac) |
| |
| def inc_ip(self, ip, i): |
| |
| ip[i] =str(int(ip[i])+1) |
| return '.'.join(ip) |
| |
| |
| def next_ip(self, ip): |
| |
| lst = ip.split('.') |
| for i in (3,0,-1): |
| if int(lst[i]) < 255: |
| return self.inc_ip(lst, i) |
| elif int(lst[i]) == 255: |
| lst[i] = '0' |
| if int(lst[i-1]) < 255: |
| return self.inc_ip(lst,i-1) |
| elif int(lst[i-2]) < 255: |
| lst[i-1] = '0' |
| return self.inc_ip(lst,i-2) |
| else: |
| break |
| |
| def randomip(self,start_ip = '10.10.0.1', end_ip = '10.10.0.100'): |
| start = list(map(int, start_ip.split("."))) |
| end = list(map(int, end_ip.split("."))) |
| temp = start |
| ip_range = [] |
| ip_range.append(start_ip) |
| while temp != end: |
| start[3] += 1 |
| for i in (3, 2, 1): |
| if temp[i] == 255: |
| temp[i] = 0 |
| temp[i-1] += 1 |
| ip_range.append(".".join(map(str, temp))) |
| return random.choice(ip_range) |
| |
| def ip_range(self,start_ip = '10.10.0.1', end_ip = '10.10.0.100'): |
| start = list(map(int, start_ip.split("."))) |
| end = list(map(int, end_ip.split("."))) |
| temp = start |
| ip_range = [] |
| ip_range.append(start_ip) |
| while temp != end: |
| start[3] += 1 |
| for i in (3, 2, 1): |
| if temp[i] == 255: |
| temp[i] = 0 |
| temp[i-1] += 1 |
| ip_range.append(".".join(map(str, temp))) |
| return ip_range |
| |
| def to_egress_ip(self, ip): |
| lst=ip.split('.') |
| lst[0] = '182' |
| return '.'.join(lst) |
| |
| @classmethod |
| def setUpClass(cls): |
| cls.olt = OltConfig() |
| cls.port_map, _ = cls.olt.olt_port_map() |
| if not cls.port_map: |
| cls.port_map = cls.default_port_map |
| cls.device_id = OnosCtrl.get_device_id() |
| |
| class cluster_proxyarp(): |
| #apps = ('org.onosproject.vrouter','org.onosproject.proxyarp') |
| app = 'org.onosproject.proxyarp' |
| device_id = 'of:' + get_mac() |
| device_dict = { "devices" : { |
| "{}".format(device_id) : { |
| "basic" : { |
| "driver" : "softrouter" |
| } |
| } |
| }, |
| } |
| test_path = os.path.dirname(os.path.realpath(__file__)) |
| onos_config_path = os.path.join(test_path, '..', 'setup/onos-config') |
| GATEWAY = '192.168.10.50' |
| INGRESS_PORT = 1 |
| EGRESS_PORT = 2 |
| MAX_PORTS = 100 |
| hosts_list = [ ('192.168.10.1', '00:00:00:00:00:01'), ('192.168.11.1', '00:00:00:00:02:01'), ] |
| |
| olt_conf_file = os.getenv('OLT_CONFIG_FILE', os.path.join(os.path.dirname(os.path.realpath(__file__)), '../setup/olt_config.json')) |
| |
| @classmethod |
| def setUpClass(cls): |
| cls.olt = OltConfig() |
| cls.port_map, _ = cls.olt.olt_port_map() |
| print('port map in proxyarp setUpClass is %s'%cls.port_map) |
| if not cls.port_map: |
| cls.port_map = g_subscriber_port_map |
| time.sleep(3) |
| cls.load_device_id() |
| |
| @classmethod |
| def load_device_id(cls): |
| did = OnosCtrl.get_device_id() |
| cls.device_id = did |
| cls.device_dict = { "devices" : { |
| "{}".format(did) : { |
| "basic" : { |
| "driver" : "softrouter" |
| } |
| } |
| }, |
| } |
| def cliEnter(self): |
| retries = 0 |
| while retries < 3: |
| self.cli = OnosCliDriver(connect = True) |
| if self.cli.handle: |
| break |
| else: |
| retries += 1 |
| time.sleep(2) |
| |
| def cliExit(self): |
| self.cli.disconnect() |
| |
| @classmethod |
| def interface_config_load(cls, interface_cfg = None): |
| if type(interface_cfg) is tuple: |
| res = [] |
| for v in interface_cfg: |
| if type(v) == list: |
| pass |
| else: |
| res += v.items() |
| config = dict(res) |
| else: |
| config = interface_cfg |
| cfg = json.dumps(config) |
| #with open('{}/network-cfg.json'.format(cls.onos_config_path), 'w') as f: |
| # f.write(cfg) |
| #return cord_test_onos_restart(config=config) |
| |
| @classmethod |
| def host_config_load(cls, host_config = None, controller=None): |
| for host in host_config: |
| status, code = OnosCtrl(cls.app).host_config(host,onos_ip=controller) |
| if status is False: |
| log_test.info('JSON request returned status %d' %code) |
| assert_equal(status, True) |
| |
| @classmethod |
| def generate_interface_config(cls, hosts = 1): |
| num = 0 |
| start_host = ( 192 << 24) | ( 168 << 16) | (10 << 8) | 0 |
| end_host = ( 200 << 24 ) | (168 << 16) | (10 << 8) | 0 |
| ports_dict = { 'ports' : {} } |
| interface_list = [] |
| hosts_list = [] |
| for n in xrange(start_host, end_host, 256): |
| port_map = ports_dict['ports'] |
| port = num + 1 if num < cls.MAX_PORTS - 1 else cls.MAX_PORTS - 1 |
| device_port_key = '{0}/{1}'.format(cls.device_id, port) |
| try: |
| interfaces = port_map[device_port_key]['interfaces'] |
| except: |
| port_map[device_port_key] = { 'interfaces' : [] } |
| interfaces = port_map[device_port_key]['interfaces'] |
| ip = n + 1 |
| host_ip = n + 2 |
| ips = '%d.%d.%d.%d/24'%( (ip >> 24) & 0xff, ( (ip >> 16) & 0xff ), ( (ip >> 8 ) & 0xff ), ip & 0xff) |
| host = '%d.%d.%d.%d' % ( (host_ip >> 24) & 0xff, ( ( host_ip >> 16) & 0xff ), ( (host_ip >> 8 ) & 0xff ), host_ip & 0xff ) |
| mac = RandMAC()._fix() |
| hosts_list.append((host, mac)) |
| if num < cls.MAX_PORTS - 1: |
| interface_dict = { 'name' : 'b1-{}'.format(port), 'ips': [ips], 'mac' : mac } |
| interfaces.append(interface_dict) |
| interface_list.append(interface_dict['name']) |
| else: |
| interfaces[0]['ips'].append(ips) |
| num += 1 |
| if num == hosts: |
| break |
| cls.hosts_list = hosts_list |
| return (cls.device_dict, ports_dict, hosts_list) |
| |
| @classmethod |
| def generate_host_config(cls): |
| num = 0 |
| hosts_dict = {} |
| for host, mac in cls.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.device_id), 'port': port}} |
| num += 1 |
| return hosts_dict.values() |
| |
| @classmethod |
| def proxyarp_activate(cls, deactivate = False,controller=None): |
| app = 'org.onosproject.proxyarp' |
| onos_ctrl = OnosCtrl(app,controller=controller) |
| if deactivate is True: |
| onos_ctrl.deactivate() |
| else: |
| onos_ctrl.activate() |
| time.sleep(3) |
| |
| @classmethod |
| def proxyarp_config(cls, hosts = 1,controller=None): |
| proxyarp_configs = cls.generate_interface_config(hosts = hosts) |
| cls.interface_config_load(interface_cfg = proxyarp_configs) |
| hostcfg = cls.generate_host_config() |
| cls.host_config_load(host_config = hostcfg,controller=controller) |
| return proxyarp_configs |
| |
| def proxyarp_arpreply_verify(self, ingress, hostip, hostmac, PositiveTest=True): |
| #log_test.info('verifying arp reply for host ip %s host mac %s on interface %s'%(hostip ,hostmac ,self.port_map[ingress])) |
| self.success = False |
| def recv_task(): |
| def recv_cb(pkt): |
| log_test.info('Arp Reply seen with source Mac is %s' %(pkt[ARP].hwsrc)) |
| self.success = True if PositiveTest == True else False |
| sniff(count=1, timeout=2, lfilter = lambda p: ARP in p and p[ARP].op == 2 and p[ARP].hwsrc == hostmac, |
| prn = recv_cb, iface = self.port_map[ingress]) |
| t = threading.Thread(target = recv_task) |
| t.start() |
| pkt = (Ether(dst = 'ff:ff:ff:ff:ff:ff')/ARP(op=1,pdst=hostip)) |
| log_test.info('sending arp request for dest ip %s on interface %s' % |
| (hostip, self.port_map[ingress])) |
| sendp( pkt, count = 10, iface = self.port_map[ingress]) |
| t.join() |
| if PositiveTest: |
| assert_equal(self.success, True) |
| else: |
| assert_equal(self.success, False) |
| |
| def proxyarp_hosts_verify(self, hosts = 1,PositiveTest = True): |
| log_test.info('verifying arp reply for host ip host mac on interface %s'%(self.port_map[2])) |
| _,_,hosts_config = self.proxyarp_config(hosts = hosts) |
| log_test.info('\nhosts_config %s and its type %s'%(hosts_config,type(hosts_config))) |
| self.cliEnter() |
| connected_hosts = json.loads(self.cli.hosts(jsonFormat = True)) |
| log_test.info('Discovered hosts: %s' %connected_hosts) |
| #We read from cli if we expect less number of routes to avoid cli timeouts |
| if hosts <= 10000: |
| assert_equal(len(connected_hosts), hosts) |
| ingress = hosts+1 |
| for hostip, hostmac in hosts_config: |
| self.proxyarp_arpreply_verify(ingress,hostip,hostmac,PositiveTest = PositiveTest) |
| time.sleep(1) |
| self.cliExit() |
| return True |
| |
| class cluster_vrouter(object): |
| apps = ('org.onosproject.vrouter', 'org.onosproject.fwd') |
| device_id = 'of:' + get_mac() |
| vrouter_device_dict = { "devices" : { |
| "{}".format(device_id) : { |
| "basic" : { |
| "driver" : "softrouter" |
| } |
| } |
| }, |
| } |
| zebra_conf = ''' |
| password zebra |
| log stdout |
| service advanced-vty |
| ! |
| !debug zebra rib |
| !debug zebra kernel |
| !debug zebra fpm |
| ! |
| !interface eth1 |
| ! ip address 10.10.0.3/16 |
| line vty |
| exec-timeout 0 0 |
| ''' |
| test_path = os.path.dirname(os.path.realpath(__file__)) |
| quagga_config_path = os.path.join(test_path, '..', 'setup/quagga-config') |
| onos_config_path = os.path.join(test_path, '..', 'setup/onos-config') |
| GATEWAY = '192.168.10.50' |
| INGRESS_PORT = 1 |
| EGRESS_PORT = 2 |
| MAX_PORTS = 100 |
| peer_list = [ ('192.168.10.1', '00:00:00:00:00:01'), ('192.168.11.1', '00:00:00:00:02:01'), ] |
| network_list = [] |
| network_mask = 24 |
| default_routes_address = ('11.10.10.0/24',) |
| default_peer_address = peer_list |
| quagga_ip = os.getenv('QUAGGA_IP') |
| |
| @classmethod |
| def setUpClass(cls): |
| ''' Activate the vrouter apps''' |
| cls.olt = OltConfig() |
| cls.port_map, _ = cls.olt.olt_port_map() |
| if not cls.port_map: |
| cls.port_map = g_subscriber_port_map |
| time.sleep(3) |
| cls.load_device_id() |
| |
| @classmethod |
| def tearDownClass(cls): |
| '''Deactivate the vrouter apps''' |
| #cls.vrouter_host_unload() |
| cls.start_onos(network_cfg = {}) |
| #cls.vrouter_activate(cls, deactivate = True) |
| |
| |
| @classmethod |
| def load_device_id(cls): |
| did = OnosCtrl.get_device_id() |
| cls.device_id = did |
| cls.vrouter_device_dict = { "devices" : { |
| "{}".format(did) : { |
| "basic" : { |
| "driver" : "softrouter" |
| } |
| } |
| }, |
| } |
| |
| def cliEnter(self,controller=None): |
| retries = 0 |
| while retries < 3: |
| self.cli = OnosCliDriver(connect = True,controller=controller) |
| if self.cli.handle: |
| break |
| else: |
| retries += 1 |
| time.sleep(2) |
| |
| def cliExit(self): |
| self.cli.disconnect() |
| |
| @classmethod |
| def onos_load_config(cls, config,controller=None): |
| status, code = OnosCtrl.config(config,controller=controller) |
| if status is False: |
| log_test.info('JSON request returned status %d' %code) |
| assert_equal(status, True) |
| |
| @classmethod |
| def vrouter_config_get(cls, networks = 4, peers = 1, peer_address = None, |
| route_update = None, router_address = None): |
| vrouter_configs = cls.generate_vrouter_conf(networks = networks, peers = peers, |
| peer_address = peer_address, router_address = router_address) |
| return vrouter_configs |
| |
| @classmethod |
| def vrouter_host_load(cls,peer_address = None,controller=None): |
| index = 1 |
| hosts_dict = {} |
| peer_info = peer_address if peer_address is not None else cls.peer_list |
| for host,_ in peer_info: |
| #iface = cls.port_map[index] |
| mac = RandMAC()._fix() |
| #port = num + 1 if num < cls.MAX_PORTS - 1 else cls.MAX_PORTS - 1 |
| log_test.info('creating host with ip %s and mac %s'%(host,mac)) |
| hosts_dict[host] = {'mac':mac, 'vlan':'none', 'ipAddresses':[host], 'location':{ 'elementId' : '{}'.format(cls.device_id), 'port': index}} |
| index += 1 |
| for host in hosts_dict.values(): |
| status, code = OnosCtrl.host_config(host,onos_ip=controller) |
| if status is False: |
| log_test.info('JSON request returned status %d' %code) |
| return False |
| return True |
| |
| """@classmethod |
| def vrouter_host_load(cls, peer_address = None): |
| #cls.setUpClass() |
| index = 1 |
| peer_info = peer_address if peer_address is not None else cls.peer_list |
| |
| for host,_ in peer_info: |
| iface = cls.port_map[index] |
| index += 1 |
| log_test.info('Assigning ip %s to interface %s' %(host, iface)) |
| config_cmds = ( 'ifconfig {} 0'.format(iface), |
| 'ifconfig {0} {1}'.format(iface, host), |
| 'arping -I {0} {1} -c 2'.format(iface, host), |
| ) |
| for cmd in config_cmds: |
| os.system(cmd) |
| """ |
| @classmethod |
| def vrouter_host_unload(cls, peer_address = None): |
| index = 1 |
| peer_info = peer_address if peer_address is not None else cls.peer_list |
| |
| for host,_ in peer_info: |
| iface = cls.port_map[index] |
| index += 1 |
| config_cmds = ('ifconfig {} 0'.format(iface), ) |
| for cmd in config_cmds: |
| os.system(cmd) |
| |
| @classmethod |
| def start_onos(cls, network_cfg = None): |
| if type(network_cfg) is tuple: |
| res = [] |
| for v in network_cfg: |
| res += v.items() |
| config = dict(res) |
| else: |
| config = network_cfg |
| cfg = json.dumps(config) |
| log_test.info('Restarting ONOS with new network configuration %s'%config) |
| #return cord_test_onos_restart(config = config) |
| with open('{}/network-cfg.json'.format(cls.onos_config_path), 'w') as f: |
| f.write(cfg) |
| return cord_test_onos_restart(config=config) |
| |
| @classmethod |
| def start_quagga(cls, networks = 4, peer_address = None, router_address = None): |
| log_test.info('Restarting Quagga container with configuration for %d networks' %(networks)) |
| config = cls.generate_conf(networks = networks, peer_address = peer_address, router_address = router_address) |
| if networks <= 10000: |
| boot_delay = 25 |
| else: |
| delay_map = [60, 100, 150, 200, 300, 450, 600, 800, 1000, 1200] |
| n = min(networks/100000, len(delay_map)-1) |
| boot_delay = delay_map[n] |
| cord_test_quagga_restart(config = config, boot_delay = boot_delay) |
| |
| @classmethod |
| def generate_vrouter_conf(cls, networks = 4, peers = 1, peer_address = None, router_address = None): |
| num = 0 |
| if peer_address is None: |
| start_peer = ( 192 << 24) | ( 168 << 16) | (10 << 8) | 0 |
| end_peer = ( 200 << 24 ) | (168 << 16) | (10 << 8) | 0 |
| else: |
| ip = peer_address[0][0] |
| start_ip = ip.split('.') |
| start_peer = ( int(start_ip[0]) << 24) | ( int(start_ip[1]) << 16) | ( int(start_ip[2]) << 8) | 0 |
| end_peer = ((int(start_ip[0]) + 8) << 24 ) | (int(start_ip[1]) << 16) | (int(start_ip[2]) << 8) | 0 |
| local_network = end_peer + 1 |
| ports_dict = { 'ports' : {} } |
| interface_list = [] |
| peer_list = [] |
| for n in xrange(start_peer, end_peer, 256): |
| port_map = ports_dict['ports'] |
| port = num + 1 if num < cls.MAX_PORTS - 1 else cls.MAX_PORTS - 1 |
| device_port_key = '{0}/{1}'.format(cls.device_id, port) |
| try: |
| interfaces = port_map[device_port_key]['interfaces'] |
| except: |
| port_map[device_port_key] = { 'interfaces' : [] } |
| interfaces = port_map[device_port_key]['interfaces'] |
| ip = n + 2 |
| peer_ip = n + 1 |
| ips = '%d.%d.%d.%d/24'%( (ip >> 24) & 0xff, ( (ip >> 16) & 0xff ), ( (ip >> 8 ) & 0xff ), ip & 0xff) |
| peer = '%d.%d.%d.%d' % ( (peer_ip >> 24) & 0xff, ( ( peer_ip >> 16) & 0xff ), ( (peer_ip >> 8 ) & 0xff ), peer_ip & 0xff ) |
| mac = RandMAC()._fix() |
| peer_list.append((peer, mac)) |
| if num < cls.MAX_PORTS - 1: |
| interface_dict = { 'name' : 'b1-{}'.format(port), 'ips': [ips], 'mac' : mac } |
| interfaces.append(interface_dict) |
| interface_list.append(interface_dict['name']) |
| else: |
| interfaces[0]['ips'].append(ips) |
| num += 1 |
| if num == peers: |
| break |
| quagga_dict = { 'apps': { 'org.onosproject.router' : { 'router' : {}, 'bgp' : { 'bgpSpeakers' : [] } } } } |
| quagga_router_dict = quagga_dict['apps']['org.onosproject.router']['router'] |
| quagga_router_dict['ospfEnabled'] = True |
| quagga_router_dict['interfaces'] = interface_list |
| quagga_router_dict['controlPlaneConnectPoint'] = '{0}/{1}'.format(cls.device_id, peers + 1) |
| |
| #bgp_speaker_dict = { 'apps': { 'org.onosproject.router' : { 'bgp' : { 'bgpSpeakers' : [] } } } } |
| bgp_speakers_list = quagga_dict['apps']['org.onosproject.router']['bgp']['bgpSpeakers'] |
| speaker_dict = {} |
| speaker_dict['name'] = 'bgp{}'.format(peers+1) |
| speaker_dict['connectPoint'] = '{0}/{1}'.format(cls.device_id, peers + 1) |
| speaker_dict['peers'] = peer_list |
| bgp_speakers_list.append(speaker_dict) |
| cls.peer_list = peer_list |
| return (cls.vrouter_device_dict, ports_dict, quagga_dict) |
| |
| @classmethod |
| def generate_conf(cls, networks = 4, peer_address = None, router_address = None): |
| num = 0 |
| if router_address is None: |
| start_network = ( 11 << 24) | ( 10 << 16) | ( 10 << 8) | 0 |
| end_network = ( 172 << 24 ) | ( 0 << 16) | (0 << 8) | 0 |
| network_mask = 24 |
| else: |
| ip = router_address |
| start_ip = ip.split('.') |
| network_mask = int(start_ip[3].split('/')[1]) |
| start_ip[3] = (start_ip[3].split('/'))[0] |
| start_network = (int(start_ip[0]) << 24) | ( int(start_ip[1]) << 16) | ( int(start_ip[2]) << 8) | 0 |
| end_network = (172 << 24 ) | (int(start_ip[1]) << 16) | (int(start_ip[2]) << 8) | 0 |
| net_list = [] |
| peer_list = peer_address if peer_address is not None else cls.peer_list |
| network_list = [] |
| for n in xrange(start_network, end_network, 256): |
| net = '%d.%d.%d.0'%( (n >> 24) & 0xff, ( ( n >> 16) & 0xff ), ( (n >> 8 ) & 0xff ) ) |
| network_list.append(net) |
| gateway = peer_list[num % len(peer_list)][0] |
| net_route = 'ip route {0}/{1} {2}'.format(net, network_mask, gateway) |
| net_list.append(net_route) |
| num += 1 |
| if num == networks: |
| break |
| cls.network_list = network_list |
| cls.network_mask = network_mask |
| zebra_routes = '\n'.join(net_list) |
| #log_test.info('Zebra routes: \n:%s\n' %cls.zebra_conf + zebra_routes) |
| return cls.zebra_conf + zebra_routes |
| |
| @classmethod |
| def vrouter_activate(cls, deactivate = False,controller=None): |
| app = 'org.onosproject.vrouter' |
| onos_ctrl = OnosCtrl(app,controller=controller) |
| if deactivate is True: |
| onos_ctrl.deactivate() |
| else: |
| onos_ctrl.activate() |
| time.sleep(3) |
| |
| @classmethod |
| def vrouter_configure(cls, networks = 4, peers = 1, peer_address = None, |
| route_update = None, router_address = None, time_expire = None, adding_new_routes = None,controller=None): |
| vrouter_configs = cls.vrouter_config_get(networks = networks, peers = peers, |
| peer_address = peer_address, route_update = route_update) |
| cls.start_onos(network_cfg = vrouter_configs) |
| cls.vrouter_host_load(controller=controller) |
| ##Start quagga |
| cls.start_quagga(networks = networks, peer_address = peer_address, router_address = router_address) |
| return vrouter_configs |
| |
| def vrouter_port_send_recv(self, ingress, egress, dst_mac, dst_ip, positive_test = True): |
| src_mac = '00:00:00:00:00:02' |
| src_ip = '1.1.1.1' |
| self.success = False if positive_test else True |
| timeout = 10 if positive_test else 1 |
| count = 2 if positive_test else 1 |
| self.start_sending = True |
| def recv_task(): |
| def recv_cb(pkt): |
| log_test.info('Pkt seen with ingress ip %s, egress ip %s' %(pkt[IP].src, pkt[IP].dst)) |
| self.success = True if positive_test else False |
| sniff(count=count, timeout=timeout, |
| lfilter = lambda p: IP in p and p[IP].dst == dst_ip and p[IP].src == src_ip, |
| prn = recv_cb, iface = self.port_map[ingress]) |
| self.start_sending = False |
| |
| t = threading.Thread(target = recv_task) |
| t.start() |
| L2 = Ether(src = src_mac, dst = dst_mac) |
| L3 = IP(src = src_ip, dst = dst_ip) |
| pkt = L2/L3 |
| log_test.info('Sending a packet with dst ip %s, dst mac %s on port %s to verify if flows are correct' % |
| (dst_ip, dst_mac, self.port_map[egress])) |
| while self.start_sending is True: |
| sendp(pkt, count=50, iface = self.port_map[egress]) |
| t.join() |
| assert_equal(self.success, True) |
| |
| def vrouter_traffic_verify(self, positive_test = True, peer_address = None): |
| if peer_address is None: |
| peers = len(self.peer_list) |
| peer_list = self.peer_list |
| else: |
| peers = len(peer_address) |
| peer_list = peer_address |
| egress = peers + 1 |
| num = 0 |
| num_hosts = 5 if positive_test else 1 |
| src_mac = '00:00:00:00:00:02' |
| src_ip = '1.1.1.1' |
| if self.network_mask != 24: |
| peers = 1 |
| for network in self.network_list: |
| num_ips = num_hosts |
| octets = network.split('.') |
| for i in xrange(num_ips): |
| octets[-1] = str(int(octets[-1]) + 1) |
| dst_ip = '.'.join(octets) |
| dst_mac = peer_list[ num % peers ] [1] |
| port = (num % peers) |
| ingress = port + 1 |
| #Since peers are on the same network |
| ##Verify if flows are setup by sending traffic across |
| self.vrouter_port_send_recv(ingress, egress, dst_mac, dst_ip, positive_test = positive_test) |
| num += 1 |
| |
| def vrouter_network_verify(self, networks, peers = 1, positive_test = True, |
| start_network = None, start_peer_address = None, route_update = None, |
| invalid_peers = None, time_expire = None, unreachable_route_traffic = None, |
| deactivate_activate_vrouter = None, adding_new_routes = None,controller=None): |
| |
| _, ports_map, egress_map = self.vrouter_configure(networks = networks, peers = peers, |
| peer_address = start_peer_address, |
| route_update = route_update, |
| router_address = start_network, |
| time_expire = time_expire, |
| adding_new_routes = adding_new_routes, |
| controller=controller) |
| self.cliEnter(controller=controller) |
| ##Now verify |
| hosts = json.loads(self.cli.hosts(jsonFormat = True)) |
| log_test.info('Discovered hosts: %s' %hosts) |
| ##We read from cli if we expect less number of routes to avoid cli timeouts |
| if networks <= 10000: |
| routes = json.loads(self.cli.routes(jsonFormat = True)) |
| #log_test.info('Routes: %s' %routes) |
| if start_network is not None: |
| if start_network.split('/')[1] is 24: |
| assert_equal(len(routes['routes4']), networks) |
| if start_network.split('/')[1] is not 24: |
| assert_equal(len(routes['routes4']), 1) |
| if start_network is None and invalid_peers is None: |
| assert_equal(len(routes['routes4']), networks) |
| if invalid_peers is not None: |
| assert_equal(len(routes['routes4']), 0) |
| flows = json.loads(self.cli.flows(jsonFormat = True)) |
| flows = filter(lambda f: f['flows'], flows) |
| #log_test.info('Flows: %s' %flows) |
| assert_not_equal(len(flows), 0) |
| if invalid_peers is None: |
| self.vrouter_traffic_verify() |
| if positive_test is False: |
| self.vrouter_network_verify_negative(networks, peers = peers) |
| if time_expire is True: |
| self.start_quagga(networks = networks, peer_address = start_peer_address, router_address = '12.10.10.1/24') |
| self.vrouter_traffic_verify() |
| if unreachable_route_traffic is True: |
| network_list_backup = self.network_list |
| self.network_list = ['2.2.2.2','3.3.3.3','4.4.4.4','5.5.5.5'] |
| self.vrouter_traffic_verify(positive_test = False) |
| self.network_list = network_list_backup |
| if deactivate_activate_vrouter is True: |
| log_test.info('Deactivating vrouter app in ONOS controller for negative scenario') |
| self.vrouter_activate(deactivate = True) |
| #routes = json.loads(self.cli.routes(jsonFormat = False, cmd_exist = False)) |
| #assert_equal(len(routes['routes4']), 'Command not found') |
| log_test.info('Activating vrouter app again in ONOS controller for negative scenario') |
| self.vrouter_activate(deactivate = False) |
| routes = json.loads(self.cli.routes(jsonFormat = True)) |
| assert_equal(len(routes['routes4']), networks) |
| self.vrouter_traffic_verify() |
| self.cliExit() |
| return True |
| |
| def vrouter_network_verify_negative(self, networks, peers = 1): |
| ##Stop quagga. Test traffic again to see if flows were removed |
| log_test.info('Stopping Quagga container') |
| cord_test_quagga_stop() |
| if networks <= 10000: |
| routes = json.loads(self.cli.routes(jsonFormat = True)) |
| #Verify routes have been removed |
| if routes and routes.has_key('routes4'): |
| assert_equal(len(routes['routes4']), 0) |
| self.vrouter_traffic_verify(positive_test = False) |
| log_test.info('OVS flows have been removed successfully after Quagga was stopped') |
| self.start_quagga(networks = networks) |
| ##Verify the flows again after restarting quagga back |
| if networks <= 10000: |
| routes = json.loads(self.cli.routes(jsonFormat = True)) |
| assert_equal(len(routes['routes4']), networks) |
| self.vrouter_traffic_verify() |
| log_test.info('OVS flows have been successfully reinstalled after Quagga was restarted') |
| |
| def quagga_shell(self, cmd): |
| shell_cmds = ('vtysh', '"conf t"', '"{}"'.format(cmd)) |
| quagga_cmd = ' -c '.join(shell_cmds) |
| |
| return cord_test_quagga_shell(quagga_cmd) |
| |
| class cluster_acl(object): |
| app = 'org.onosproject.acl' |
| device_id = 'of:' + get_mac('ovsbr0') |
| test_path = os.path.dirname(os.path.realpath(__file__)) |
| onos_config_path = os.path.join(test_path, '..', 'setup/onos-config') |
| GATEWAY = '192.168.10.50' |
| INGRESS_PORT = 1 |
| EGRESS_PORT = 2 |
| ingress_iface = 1 |
| egress_iface = 2 |
| MAX_PORTS = 100 |
| CURRENT_PORT_NUM = egress_iface |
| ACL_SRC_IP = '192.168.20.3/32' |
| ACL_DST_IP = '192.168.30.2/32' |
| ACL_SRC_IP_RULE_2 = '192.168.40.3/32' |
| ACL_DST_IP_RULE_2 = '192.168.50.2/32' |
| ACL_SRC_IP_PREFIX_24 = '192.168.20.3/24' |
| ACL_DST_IP_PREFIX_24 = '192.168.30.2/24' |
| HOST_DST_IP = '192.168.30.0/24' |
| HOST_DST_IP_RULE_2 = '192.168.50.0/24' |
| |
| @classmethod |
| def setUpClass(cls): |
| cls.olt = OltConfig() |
| cls.port_map,_ = cls.olt.olt_port_map() |
| if not cls.port_map: |
| cls.port_map = g_subscriber_port_map |
| time.sleep(3) |
| log_test.info('port_map = %s'%cls.port_map[1] ) |
| |
| @classmethod |
| def tearDownClass(cls): |
| '''Deactivate the acl app''' |
| def setUp(self,controller=None): |
| self.setUpClass() |
| ''' Activate the acl app''' |
| self.maxDiff = None ##for assert_equal compare outputs on failure |
| self.onos_ctrl = OnosCtrl(self.app,controller=controller) |
| status, _ = self.onos_ctrl.activate() |
| assert_equal(status, True) |
| time.sleep(1) |
| #status, _ = ACLTest.remove_acl_rule() |
| #log_test.info('Start setup') |
| #assert_equal(status, True) |
| |
| def tearDown(self): |
| '''Deactivate the acl app''' |
| log_test.info('Tear down setup') |
| self.CURRENT_PORT_NUM = 4 |
| |
| def cliEnter(self): |
| retries = 0 |
| while retries < 3: |
| self.cli = OnosCliDriver(connect = True) |
| if self.cli.handle: |
| break |
| else: |
| retries += 1 |
| time.sleep(2) |
| |
| def cliExit(self): |
| self.cli.disconnect() |
| |
| @classmethod |
| def acl_hosts_add(cls, dstHostIpMac, egress_iface_count = 1, egress_iface_num = None): |
| cls.setUpClass() |
| index = 0 |
| if egress_iface_num is None: |
| egress_iface_num = cls.egress_iface |
| for ip,_ in dstHostIpMac: |
| egress = cls.port_map[egress_iface_num] |
| log_test.info('Assigning ip %s to interface %s' %(ip, egress)) |
| config_cmds_egress = ( 'ifconfig {} 0'.format(egress), |
| 'ifconfig {0} up'.format(egress), |
| 'ifconfig {0} {1}'.format(egress, ip), |
| 'arping -I {0} {1} -c 2'.format(egress, ip.split('/')[0]), |
| 'ifconfig {0}'.format(egress), |
| ) |
| for cmd in config_cmds_egress: |
| os.system(cmd) |
| index += 1 |
| if index == egress_iface_count: |
| break |
| egress_iface_count += 1 |
| egress_iface_num += 1 |
| |
| |
| @classmethod |
| def acl_hosts_remove(cls, egress_iface_count = 1, egress_iface_num = None): |
| cls.setUpClass() |
| if egress_iface_num is None: |
| egress_iface_num = cls.egress_iface |
| n = 0 |
| for n in range(egress_iface_count): |
| egress = cls.port_map[egress_iface_num] |
| config_cmds_egress = ('ifconfig {} 0'.format(egress)) |
| os.system(config_cmds_egress) |
| egress_iface_num += 1 |
| |
| def acl_rule_traffic_send_recv(self, srcMac, dstMac, srcIp, dstIp, ingress =None, egress=None, ip_proto=None, dstPortNum = None, positive_test = True): |
| self.setUpClass() |
| if ingress is None: |
| ingress = self.ingress_iface |
| if egress is None: |
| egress = self.egress_iface |
| ingress = self.port_map[ingress] |
| egress = self.port_map[egress] |
| self.success = False if positive_test else True |
| timeout = 10 if positive_test else 1 |
| count = 2 if positive_test else 1 |
| self.start_sending = True |
| def recv_task(): |
| def recv_cb(pkt): |
| log_test.info('Pkt seen with ingress ip %s, egress ip %s' %(pkt[IP].src, pkt[IP].dst)) |
| self.success = True if positive_test else False |
| sniff(count=count, timeout=timeout, |
| lfilter = lambda p: IP in p and p[IP].dst == dstIp.split('/')[0] and p[IP].src == srcIp.split('/')[0], |
| prn = recv_cb, iface = egress) |
| self.start_sending = False |
| |
| t = threading.Thread(target = recv_task) |
| t.start() |
| L2 = Ether(src = srcMac, dst = dstMac) |
| L3 = IP(src = srcIp.split('/')[0], dst = dstIp.split('/')[0]) |
| pkt = L2/L3 |
| log_test.info('Sending a packet with dst ip %s, src ip %s , dst mac %s src mac %s on port %s to verify if flows are correct' % |
| (dstIp.split('/')[0], srcIp.split('/')[0], dstMac, srcMac, ingress)) |
| while self.start_sending is True: |
| sendp(pkt, count=50, iface = ingress) |
| t.join() |
| assert_equal(self.success, True) |
| |
| @classmethod |
| def onos_load_config(cls, config,controller=None): |
| status, code = OnosCtrl.config(config,controller=controller) |
| if status is False: |
| log_test.info('JSON request returned status %d' %code) |
| assert_equal(status, True) |
| |
| class cluster_dhcprelay(object): |
| app = 'org.onosproject.dhcprelay' |
| app_dhcp = 'org.onosproject.dhcp' |
| relay_interfaces_last = () |
| interface_to_mac_map = {} |
| host_ip_map = {} |
| test_path = os.path.dirname(os.path.realpath(__file__)) |
| dhcp_data_dir = os.path.join(test_path, '..', 'setup') |
| olt_conf_file = os.getenv('OLT_CONFIG_FILE', os.path.join(test_path, '..', 'setup/olt_config.json')) |
| default_config = { 'default-lease-time' : 600, 'max-lease-time' : 7200, } |
| default_options = [ ('subnet-mask', '255.255.255.0'), |
| ('broadcast-address', '192.168.1.255'), |
| ('domain-name-servers', '192.168.1.1'), |
| ('domain-name', '"mydomain.cord-tester"'), |
| ] |
| ##specify the IP for the dhcp interface matching the subnet and subnet config |
| ##this is done for each interface dhcpd server would be listening on |
| default_subnet_config = [ ('192.168.1.2', |
| ''' |
| subnet 192.168.1.0 netmask 255.255.255.0 { |
| range 192.168.1.10 192.168.1.100; |
| } |
| '''), ] |
| |
| lock = threading.Condition() |
| ip_count = 0 |
| failure_count = 0 |
| start_time = 0 |
| diff = 0 |
| |
| transaction_count = 0 |
| transactions = 0 |
| running_time = 0 |
| total_success = 0 |
| total_failure = 0 |
| onos_restartable = bool(int(os.getenv('ONOS_RESTART', 0))) |
| |
| @classmethod |
| def setUpClass(cls,controller=None): |
| log_test.info('controller ip in dhcp setup def is %s'%controller) |
| ''' Activate the dhcprelay app''' |
| OnosCtrl(cls.app_dhcp,controller=controller).deactivate() |
| time.sleep(3) |
| cls.onos_ctrl = OnosCtrl(cls.app,controller=controller) |
| status, _ = cls.onos_ctrl.activate() |
| assert_equal(status, True) |
| time.sleep(3) |
| cls.dhcp_relay_setup(controller=controller) |
| ##start dhcpd initially with default config |
| cls.dhcpd_start(controller=controller) |
| |
| @classmethod |
| def tearDownClass(cls,controller=None): |
| '''Deactivate the dhcp relay app''' |
| try: |
| os.unlink('{}/dhcpd.conf'.format(cls.dhcp_data_dir)) |
| os.unlink('{}/dhcpd.leases'.format(cls.dhcp_data_dir)) |
| except: pass |
| OnosCtrl(cls.app,controller=controller).deactivate() |
| #cls.onos_ctrl.deactivate() |
| cls.dhcpd_stop() |
| #cls.dhcp_relay_cleanup() |
| |
| @classmethod |
| def dhcp_relay_setup(cls,controller=None): |
| did = OnosCtrl.get_device_id() |
| cls.relay_device_id = did |
| cls.olt = OltConfig(olt_conf_file = cls.olt_conf_file) |
| cls.port_map, _ = cls.olt.olt_port_map() |
| if cls.port_map: |
| ##Per subscriber, we use 1 relay port |
| try: |
| relay_port = cls.port_map[cls.port_map['relay_ports'][0]] |
| except: |
| relay_port = cls.port_map['uplink'] |
| cls.relay_interface_port = relay_port |
| cls.relay_interfaces = (cls.port_map[cls.relay_interface_port],) |
| else: |
| cls.relay_interface_port = 100 |
| cls.relay_interfaces = (g_subscriber_port_map[cls.relay_interface_port],) |
| cls.relay_interfaces_last = cls.relay_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 dhcp server virtual interface on the same subnet as first client interface |
| relay_ip = cls.get_host_ip(interface_list[0][0]) |
| relay_mac = cls.get_mac(cls.port_map[cls.relay_interface_port]) |
| interface_list.append((cls.relay_interface_port, relay_ip, relay_mac)) |
| cls.onos_interface_load(interface_list,controller=controller) |
| |
| @classmethod |
| def dhcp_relay_cleanup(cls): |
| ##reset the ONOS port configuration back to default |
| 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,controller=None): |
| log_test.info('loading onos config in controller %s'%controller) |
| status, code = OnosCtrl.config(config,controller=controller) |
| 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,controller=None): |
| interface_dict = { 'ports': {} } |
| for port_num, ip, mac in interface_list: |
| port_map = interface_dict['ports'] |
| port = '{}/{}'.format(cls.relay_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,controller=controller) |
| |
| @classmethod |
| def onos_dhcp_relay_load(cls, server_ip, server_mac,controller=None): |
| relay_device_map = '{}/{}'.format(cls.relay_device_id, cls.relay_interface_port) |
| dhcp_dict = {'apps':{'org.onosproject.dhcp-relay':{'dhcprelay': |
| {'dhcpserverConnectPoint':relay_device_map, |
| 'serverip':server_ip, |
| 'servermac':server_mac |
| } |
| } |
| } |
| } |
| cls.onos_load_config(dhcp_dict,controller=controller) |
| |
| @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: |
| os.system(c) |
| @classmethod |
| |
| def dhcpd_conf_generate(cls, config = default_config, options = default_options, |
| subnet = default_subnet_config): |
| conf = '' |
| for k, v in config.items(): |
| conf += '{} {};\n'.format(k, v) |
| |
| opts = '' |
| for k, v in options: |
| opts += 'option {} {};\n'.format(k, v) |
| |
| subnet_config = '' |
| for _, v in subnet: |
| subnet_config += '{}\n'.format(v) |
| |
| return '{}{}{}'.format(conf, opts, subnet_config) |
| |
| @classmethod |
| def dhcpd_start(cls, intf_list = None, |
| config = default_config, options = default_options, |
| subnet = default_subnet_config,controller=None): |
| '''Start the dhcpd server by generating the conf file''' |
| if intf_list is None: |
| intf_list = cls.relay_interfaces |
| ##stop dhcpd if already running |
| cls.dhcpd_stop() |
| dhcp_conf = cls.dhcpd_conf_generate(config = config, options = options, |
| subnet = subnet) |
| ##first touch dhcpd.leases if it doesn't exist |
| lease_file = '{}/dhcpd.leases'.format(cls.dhcp_data_dir) |
| if os.access(lease_file, os.F_OK) is False: |
| with open(lease_file, 'w') as fd: pass |
| |
| conf_file = '{}/dhcpd.conf'.format(cls.dhcp_data_dir) |
| with open(conf_file, 'w') as fd: |
| fd.write(dhcp_conf) |
| |
| #now configure the dhcpd interfaces for various subnets |
| index = 0 |
| intf_info = [] |
| for ip,_ in subnet: |
| intf = intf_list[index] |
| mac = cls.get_mac(intf) |
| intf_info.append((ip, mac)) |
| index += 1 |
| os.system('ifconfig {} {}'.format(intf, ip)) |
| |
| intf_str = ','.join(intf_list) |
| dhcpd_cmd = '/usr/sbin/dhcpd -4 --no-pid -cf {0} -lf {1} {2}'.format(conf_file, lease_file, intf_str) |
| log_test.info('Starting DHCPD server with command: %s' %dhcpd_cmd) |
| ret = os.system(dhcpd_cmd) |
| assert_equal(ret, 0) |
| time.sleep(3) |
| cls.relay_interfaces_last = cls.relay_interfaces |
| cls.relay_interfaces = intf_list |
| cls.onos_dhcp_relay_load(*intf_info[0],controller=controller) |
| |
| @classmethod |
| def dhcpd_stop(cls): |
| os.system('pkill -9 dhcpd') |
| for intf in cls.relay_interfaces: |
| os.system('ifconfig {} 0'.format(intf)) |
| |
| cls.relay_interfaces = cls.relay_interfaces_last |
| |
| @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 stats(self,success_rate = False, only_discover = False, iface = 'veth0'): |
| |
| self.ip_count = 0 |
| self.failure_count = 0 |
| self.start_time = 0 |
| self.diff = 0 |
| self.transaction_count = 0 |
| |
| mac = self.get_mac(iface) |
| self.host_load(iface) |
| ##we use the defaults for this test that serves as an example for others |
| ##You don't need to restart dhcpd server if retaining default config |
| config = self.default_config |
| options = self.default_options |
| subnet = self.default_subnet_config |
| dhcpd_interface_list = self.relay_interfaces |
| self.dhcpd_start(intf_list = dhcpd_interface_list, |
| config = config, |
| options = options, |
| subnet = subnet) |
| self.dhcp = DHCPTest(seed_ip = '182.17.0.1', iface = iface) |
| self.start_time = time.time() |
| |
| while self.diff <= 60: |
| |
| if only_discover: |
| cip, sip, mac, _ = self.dhcp.only_discover(multiple = True) |
| log_test.info('Got dhcp client IP %s from server %s for mac %s' % |
| (cip, sip, mac)) |
| else: |
| cip, sip = self.send_recv(mac, update_seed = True, validate = False) |
| |
| if cip: |
| self.ip_count +=1 |
| elif cip == None: |
| self.failure_count += 1 |
| log_test.info('Failed to get ip') |
| if success_rate and self.ip_count > 0: |
| break |
| |
| self.diff = round(time.time() - self.start_time, 0) |
| |
| self.transaction_count = round((self.ip_count+self.failure_count)/self.diff, 2) |
| self.transactions += (self.ip_count+self.failure_count) |
| self.running_time += self.diff |
| self.total_success += self.ip_count |
| self.total_failure += self.failure_count |
| |
| def send_recv(self, mac, update_seed = False, validate = True): |
| cip, sip = self.dhcp.discover(mac = mac, update_seed = update_seed) |
| if validate: |
| assert_not_equal(cip, None) |
| assert_not_equal(sip, None) |
| log_test.info('Got dhcp client IP %s from server %s for mac %s' % |
| (cip, sip, self.dhcp.get_mac(cip)[0])) |
| return cip,sip |
| |
| class Subscriber(Channels): |
| PORT_TX_DEFAULT = 2 |
| PORT_RX_DEFAULT = 1 |
| INTF_TX_DEFAULT = 'veth2' |
| INTF_RX_DEFAULT = 'veth0' |
| STATS_RX = 0 |
| STATS_TX = 1 |
| STATS_JOIN = 2 |
| STATS_LEAVE = 3 |
| SUBSCRIBER_SERVICES = 'DHCP IGMP TLS' |
| def __init__(self, name = 'sub', service = SUBSCRIBER_SERVICES, port_map = None, |
| num = 1, channel_start = 0, |
| tx_port = PORT_TX_DEFAULT, rx_port = PORT_RX_DEFAULT, |
| iface = INTF_RX_DEFAULT, iface_mcast = INTF_TX_DEFAULT, |
| mcast_cb = None, loginType = 'wireless'): |
| self.tx_port = tx_port |
| self.rx_port = rx_port |
| self.port_map = port_map or g_subscriber_port_map |
| try: |
| self.tx_intf = self.port_map[tx_port] |
| self.rx_intf = self.port_map[rx_port] |
| except: |
| self.tx_intf = self.port_map[self.PORT_TX_DEFAULT] |
| self.rx_intf = self.port_map[self.PORT_RX_DEFAULT] |
| log_test.info('Subscriber %s, rx interface %s, uplink interface %s' %(name, self.rx_intf, self.tx_intf)) |
| Channels.__init__(self, num, channel_start = channel_start, |
| iface = self.rx_intf, iface_mcast = self.tx_intf, mcast_cb = mcast_cb) |
| self.name = name |
| self.service = service |
| self.service_map = {} |
| services = self.service.strip().split(' ') |
| for s in services: |
| self.service_map[s] = True |
| self.loginType = loginType |
| ##start streaming channels |
| self.join_map = {} |
| ##accumulated join recv stats |
| self.join_rx_stats = Stats() |
| self.recv_timeout = False |
| |
| def has_service(self, service): |
| if self.service_map.has_key(service): |
| return self.service_map[service] |
| if self.service_map.has_key(service.upper()): |
| return self.service_map[service.upper()] |
| return False |
| |
| def channel_join_update(self, chan, join_time): |
| self.join_map[chan] = ( Stats(), Stats(), Stats(), Stats() ) |
| self.channel_update(chan, self.STATS_JOIN, 1, t = join_time) |
| def channel_join(self, chan = 0, delay = 2): |
| '''Join a channel and create a send/recv stats map''' |
| if self.join_map.has_key(chan): |
| del self.join_map[chan] |
| self.delay = delay |
| chan, join_time = self.join(chan) |
| self.channel_join_update(chan, join_time) |
| return chan |
| |
| def channel_join_next(self, delay = 2): |
| '''Joins the next channel leaving the last channel''' |
| if self.last_chan: |
| if self.join_map.has_key(self.last_chan): |
| del self.join_map[self.last_chan] |
| self.delay = delay |
| chan, join_time = self.join_next() |
| self.channel_join_update(chan, join_time) |
| return chan |
| |
| def channel_jump(self, delay = 2): |
| '''Jumps randomly to the next channel leaving the last channel''' |
| if self.last_chan is not None: |
| if self.join_map.has_key(self.last_chan): |
| del self.join_map[self.last_chan] |
| self.delay = delay |
| chan, join_time = self.jump() |
| self.channel_join_update(chan, join_time) |
| return chan |
| |
| def channel_leave(self, chan = 0): |
| if self.join_map.has_key(chan): |
| del self.join_map[chan] |
| self.leave(chan) |
| |
| def channel_update(self, chan, stats_type, packets, t=0): |
| if type(chan) == type(0): |
| chan_list = (chan,) |
| else: |
| chan_list = chan |
| for c in chan_list: |
| if self.join_map.has_key(c): |
| self.join_map[c][stats_type].update(packets = packets, t = t) |
| def channel_receive(self, chan, cb = None, count = 1, timeout = 5): |
| log_test.info('Subscriber %s on port %s receiving from group %s, channel %d' % |
| (self.name, self.rx_intf, self.gaddr(chan), chan)) |
| r = self.recv(chan, cb = cb, count = count, timeout = timeout) |
| if len(r) == 0: |
| log_test.info('Subscriber %s on port %s timed out' %(self.name, self.rx_intf)) |
| else: |
| log_test.info('Subscriber %s on port %s received %d packets' %(self.name, self.rx_intf, len(r))) |
| if self.recv_timeout: |
| ##Negative test case is disabled for now |
| assert_equal(len(r), 0) |
| |
| def recv_channel_cb(self, pkt): |
| ##First verify that we have received the packet for the joined instance |
| log_test.info('Packet received for group %s, subscriber %s, port %s' % |
| (pkt[IP].dst, self.name, self.rx_intf)) |
| if self.recv_timeout: |
| return |
| chan = self.caddr(pkt[IP].dst) |
| assert_equal(chan in self.join_map.keys(), True) |
| recv_time = monotonic.monotonic() * 1000000 |
| join_time = self.join_map[chan][self.STATS_JOIN].start |
| delta = recv_time - join_time |
| self.join_rx_stats.update(packets=1, t = delta, usecs = True) |
| self.channel_update(chan, self.STATS_RX, 1, t = delta) |
| log_test.debug('Packet received in %.3f usecs for group %s after join' %(delta, pkt[IP].dst)) |
| |
| class subscriber_pool: |
| |
| def __init__(self, subscriber, test_cbs): |
| self.subscriber = subscriber |
| self.test_cbs = test_cbs |
| |
| def pool_cb(self): |
| for cb in self.test_cbs: |
| if cb: |
| self.test_status = cb(self.subscriber) |
| if self.test_status is not True: |
| ## This is chaning for other sub status has to check again |
| self.test_status = True |
| log_test.info('This service is failed and other services will not run for this subscriber') |
| break |
| log_test.info('This Subscriber is tested for multiple service eligibility ') |
| self.test_status = True |
| |
| class cluster_subscriber(object): |
| apps = ('org.opencord.aaa', 'org.onosproject.dhcp') |
| olt_apps = () #'org.opencord.cordmcast') |
| vtn_app = 'org.opencord.vtn' |
| table_app = 'org.ciena.cordigmp' |
| dhcp_server_config = { |
| "ip": "10.1.11.50", |
| "mac": "ca:fe:ca:fe:ca:fe", |
| "subnet": "255.255.252.0", |
| "broadcast": "10.1.11.255", |
| "router": "10.1.8.1", |
| "domain": "8.8.8.8", |
| "ttl": "63", |
| "delay": "2", |
| "startip": "10.1.11.51", |
| "endip": "10.1.11.100" |
| } |
| |
| aaa_loaded = False |
| test_path = os.path.dirname(os.path.realpath(__file__)) |
| table_app_file = os.path.join(test_path, '..', 'apps/ciena-cordigmp-multitable-2.0-SNAPSHOT.oar') |
| app_file = os.path.join(test_path, '..', 'apps/ciena-cordigmp-2.0-SNAPSHOT.oar') |
| onos_config_path = os.path.join(test_path, '..', 'setup/onos-config') |
| olt_conf_file = os.getenv('OLT_CONFIG_FILE', os.path.join(test_path, '..', 'setup/olt_config.json')) |
| cpqd_path = os.path.join(test_path, '..', 'setup') |
| ovs_path = cpqd_path |
| test_services = ('IGMP', 'TRAFFIC') |
| num_joins = 0 |
| num_subscribers = 0 |
| num_channels = 0 |
| recv_timeout = False |
| onos_restartable = bool(int(os.getenv('ONOS_RESTART', 0))) |
| |
| INTF_TX_DEFAULT = 'veth2' |
| INTF_RX_DEFAULT = 'veth0' |
| SUBSCRIBER_TIMEOUT = 300 |
| CLIENT_CERT = """-----BEGIN CERTIFICATE----- |
| MIICuDCCAiGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBizELMAkGA1UEBhMCVVMx |
| CzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTb21ld2hlcmUxEzARBgNVBAoTCkNpZW5h |
| IEluYy4xHjAcBgkqhkiG9w0BCQEWD2FkbWluQGNpZW5hLmNvbTEmMCQGA1UEAxMd |
| RXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTYwNjA2MjExMjI3WhcN |
| MTcwNjAxMjExMjI3WjBnMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNV |
| BAoTCkNpZW5hIEluYy4xFzAVBgNVBAMUDnVzZXJAY2llbmEuY29tMR0wGwYJKoZI |
| hvcNAQkBFg51c2VyQGNpZW5hLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC |
| gYEAwvXiSzb9LZ6c7uNziUfKvoHO7wu/uiFC5YUpXbmVGuGZizbVrny0xnR85Dfe |
| +9R4diansfDhIhzOUl1XjN3YDeSS9OeF5YWNNE8XDhlz2d3rVzaN6hIhdotBkUjg |
| rUewjTg5OFR31QEyG3v8xR3CLgiE9xQELjZbSA07pD79zuUCAwEAAaNPME0wEwYD |
| VR0lBAwwCgYIKwYBBQUHAwIwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL3d3dy5l |
| eGFtcGxlLmNvbS9leGFtcGxlX2NhLmNybDANBgkqhkiG9w0BAQUFAAOBgQDAjkrY |
| 6tDChmKbvr8w6Du/t8vHjTCoCIocHTN0qzWOeb1YsAGX89+TrWIuO1dFyYd+Z0KC |
| PDKB5j/ygml9Na+AklSYAVJIjvlzXKZrOaPmhZqDufi+rXWti/utVqY4VMW2+HKC |
| nXp37qWeuFLGyR1519Y1d6F/5XzqmvbwURuEug== |
| -----END CERTIFICATE-----""" |
| |
| CLIENT_CERT_INVALID = '''-----BEGIN CERTIFICATE----- |
| MIIDvTCCAqWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBizELMAkGA1UEBhMCVVMx |
| CzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTb21ld2hlcmUxEzARBgNVBAoTCkNpZW5h |
| IEluYy4xHjAcBgkqhkiG9w0BCQEWD2FkbWluQGNpZW5hLmNvbTEmMCQGA1UEAxMd |
| RXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTYwMzExMTg1MzM2WhcN |
| MTcwMzA2MTg1MzM2WjBnMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNV |
| BAoTCkNpZW5hIEluYy4xFzAVBgNVBAMUDnVzZXJAY2llbmEuY29tMR0wGwYJKoZI |
| hvcNAQkBFg51c2VyQGNpZW5hLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC |
| AQoCggEBAOxemcBsPn9tZsCa5o2JA6sQDC7A6JgCNXXl2VFzKLNNvB9PS6D7ZBsQ |
| 5An0zEDMNzi51q7lnrYg1XyiE4S8FzMGAFr94RlGMQJUbRD9V/oqszMX4k++iAOK |
| tIA1gr3x7Zi+0tkjVSVzXTmgNnhChAamdMsjYUG5+CY9WAicXyy+VEV3zTphZZDR |
| OjcjEp4m/TSXVPYPgYDXI40YZKX5BdvqykWtT/tIgZb48RS1NPyN/XkCYzl3bv21 |
| qx7Mc0fcEbsJBIIRYTUkfxnsilcnmLxSYO+p+DZ9uBLBzcQt+4Rd5pLSfi21WM39 |
| 2Z2oOi3vs/OYAPAqgmi2JWOv3mePa/8CAwEAAaNPME0wEwYDVR0lBAwwCgYIKwYB |
| BQUHAwIwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL3d3dy5leGFtcGxlLmNvbS9l |
| eGFtcGxlX2NhLmNybDANBgkqhkiG9w0BAQUFAAOCAQEALBzMPDTIB6sLyPl0T6JV |
| MjOkyldAVhXWiQsTjaGQGJUUe1cmUJyZbUZEc13MygXMPOM4x7z6VpXGuq1c/Vxn |
| VzQ2fNnbJcIAHi/7G8W5/SQfPesIVDsHTEc4ZspPi5jlS/MVX3HOC+BDbOjdbwqP |
| RX0JEr+uOyhjO+lRxG8ilMRACoBUbw1eDuVDoEBgErSUC44pq5ioDw2xelc+Y6hQ |
| dmtYwfY0DbvwxHtA495frLyPcastDiT/zre7NL51MyUDPjjYjghNQEwvu66IKbQ3 |
| T1tJBrgI7/WI+dqhKBFolKGKTDWIHsZXQvZ1snGu/FRYzg1l+R/jT8cRB9BDwhUt |
| yg== |
| -----END CERTIFICATE-----''' |
| @classmethod |
| def load_device_id(cls): |
| '''Configure the device id''' |
| did = OnosCtrl.get_device_id() |
| #Set the default config |
| cls.device_id = did |
| cls.device_dict = { "devices" : { |
| "{}".format(did) : { |
| "basic" : { |
| "driver" : "voltha" |
| } |
| } |
| }, |
| } |
| return did |
| |
| @classmethod |
| def setUpClass(cls,controller=None): |
| log_test.info('controller ip in cluster.py setupclass is %s'%controller) |
| '''Load the OLT config and activate relevant apps''' |
| did = cls.load_device_id() |
| network_cfg = { "devices" : { |
| "{}".format(did) : { |
| "basic" : { |
| "driver" : "voltha" |
| } |
| } |
| }, |
| } |
| ## Restart ONOS with cpqd driver config for OVS |
| print('onos restart in setUpClass') |
| cls.start_onos(network_cfg = network_cfg) |
| #status, code = OnosCtrl.config(network_cfg) |
| #if status is False: |
| # log_test.info('JSON config request for app %s returned status %d' %(app, code)) |
| #assert_equal(status, True) |
| #time.sleep(2) |
| cls.install_app_table(controller=controller) |
| cls.olt = OltConfig(olt_conf_file = cls.olt_conf_file) |
| OnosCtrl.cord_olt_config(cls.olt, controller=controller) |
| cls.port_map, cls.port_list = cls.olt.olt_port_map() |
| cls.activate_apps(cls.apps + cls.olt_apps,controller=controller) |
| |
| @classmethod |
| def tearDownClass(cls,controller=None): |
| '''Deactivate the olt apps and restart OVS back''' |
| apps = cls.olt_apps + ( cls.table_app,) |
| for app in apps: |
| onos_ctrl = OnosCtrl(app,controller=controller) |
| onos_ctrl.deactivate() |
| cls.uninstall_app_table() |
| cls.start_onos(network_cfg = {}) |
| |
| @classmethod |
| def activate_apps(cls, apps,controller=None): |
| for app in apps: |
| onos_ctrl = OnosCtrl(app,controller=controller) |
| status, _ = onos_ctrl.activate() |
| assert_equal(status, True) |
| time.sleep(2) |
| @classmethod |
| def install_app_table(cls,controller=None): |
| ##Uninstall the existing app if any |
| OnosCtrl.uninstall_app(cls.table_app,onos_ip=controller) |
| time.sleep(2) |
| log_test.info('Installing the multi table app %s for subscriber test' %(cls.table_app_file)) |
| OnosCtrl.install_app(cls.table_app_file,onos_ip=controller) |
| time.sleep(3) |
| #onos_ctrl = OnosCtrl(cls.vtn_app) |
| #onos_ctrl.deactivate() |
| |
| @classmethod |
| def uninstall_app_table(cls,controller=None): |
| ##Uninstall the table app on class exit |
| OnosCtrl.uninstall_app(cls.table_app,onos_ip=controller) |
| time.sleep(2) |
| log_test.info('Installing back the cord igmp app %s for subscriber test on exit' %(cls.app_file)) |
| OnosCtrl.install_app(cls.app_file,onos_ip=controller) |
| #onos_ctrl = OnosCtrl(cls.vtn_app) |
| #onos_ctrl.activate() |
| |
| @classmethod |
| def start_onos(cls, network_cfg = None): |
| if cls.onos_restartable is False: |
| log_test.info('ONOS restart is disabled. Skipping ONOS restart') |
| return |
| if network_cfg is None: |
| network_cfg = cls.device_dict |
| |
| if type(network_cfg) is tuple: |
| res = [] |
| for v in network_cfg: |
| res += v.items() |
| config = dict(res) |
| else: |
| config = network_cfg |
| log_test.info('Restarting ONOS with new network configuration') |
| #return cord_test_onos_restart(config = config) |
| |
| @classmethod |
| def remove_onos_config(cls): |
| try: |
| os.unlink('{}/network-cfg.json'.format(cls.onos_config_path)) |
| except: pass |
| @classmethod |
| def start_cpqd(cls, mac = '00:11:22:33:44:55'): |
| dpid = mac.replace(':', '') |
| cpqd_file = os.sep.join( (cls.cpqd_path, 'cpqd.sh') ) |
| cpqd_cmd = '{} {}'.format(cpqd_file, dpid) |
| ret = os.system(cpqd_cmd) |
| assert_equal(ret, 0) |
| time.sleep(10) |
| device_id = 'of:{}{}'.format('0'*4, dpid) |
| return device_id |
| |
| @classmethod |
| def start_ovs(cls): |
| ovs_file = os.sep.join( (cls.ovs_path, 'of-bridge.sh') ) |
| ret = os.system(ovs_file) |
| assert_equal(ret, 0) |
| time.sleep(30) |
| |
| @classmethod |
| def ovs_cleanup(cls): |
| ##For every test case, delete all the OVS groups |
| cmd = 'ovs-ofctl del-groups br-int -OOpenFlow11 >/dev/null 2>&1' |
| cord_test_shell(cmd) |
| ##Since olt config is used for this test, we just fire a careless local cmd as well |
| try: |
| os.system(cmd) |
| except: pass |
| |
| def onos_aaa_load(self,controller=None): |
| log_test.info('controller ip in cluster.py onos_aaa_load is %s'%controller) |
| if self.aaa_loaded: |
| return |
| OnosCtrl.aaa_load_config(controller = controller) |
| self.aaa_loaded = True |
| |
| def onos_dhcp_table_load(self, config = None,controller=None): |
| log_test.info('controller ip in cluster.py onos_dhcp_table_load is %s'%controller) |
| dhcp_dict = {'apps' : { 'org.onosproject.dhcp' : { 'dhcp' : copy.copy(self.dhcp_server_config) } } } |
| dhcp_config = dhcp_dict['apps']['org.onosproject.dhcp']['dhcp'] |
| if config: |
| for k in config.keys(): |
| if dhcp_config.has_key(k): |
| dhcp_config[k] = config[k] |
| self.onos_load_config('org.onosproject.dhcp', dhcp_dict,controller=controller) |
| |
| def onos_load_config(self, app, config,controller=None): |
| log_test.info('controller ip in cluster.py onos_load_config is %s'%controller) |
| status, code = OnosCtrl(controller=controller).config(config) |
| if status is False: |
| log_test.info('JSON config request for app %s returned status %d' %(app, code)) |
| assert_equal(status, True) |
| time.sleep(2) |
| def dhcp_sndrcv(self, dhcp, update_seed = False): |
| cip, sip = dhcp.discover(update_seed = update_seed) |
| assert_not_equal(cip, None) |
| assert_not_equal(sip, None) |
| log_test.info('Got dhcp client IP %s from server %s for mac %s' % |
| (cip, sip, dhcp.get_mac(cip)[0])) |
| return cip,sip |
| |
| def dhcp_request(self, subscriber, seed_ip = '10.10.10.1', update_seed = False): |
| config = {'startip':'10.10.10.20', 'endip':'10.10.10.200', |
| 'ip':'10.10.10.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'10.10.10.255', 'router':'10.10.10.1'} |
| self.onos_dhcp_table_load(config) |
| dhcp = DHCPTest(seed_ip = seed_ip, iface = subscriber.iface) |
| cip, sip = self.dhcp_sndrcv(dhcp, update_seed = update_seed) |
| return cip, sip |
| |
| def recv_channel_cb(self, pkt): |
| ##First verify that we have received the packet for the joined instance |
| chan = self.subscriber.caddr(pkt[IP].dst) |
| assert_equal(chan in self.subscriber.join_map.keys(), True) |
| recv_time = monotonic.monotonic() * 1000000 |
| join_time = self.subscriber.join_map[chan][self.subscriber.STATS_JOIN].start |
| delta = recv_time - join_time |
| self.subscriber.join_rx_stats.update(packets=1, t = delta, usecs = True) |
| self.subscriber.channel_update(chan, self.subscriber.STATS_RX, 1, t = delta) |
| log_test.debug('Packet received in %.3f usecs for group %s after join' %(delta, pkt[IP].dst)) |
| self.test_status = True |
| |
| def traffic_verify(self, subscriber): |
| if subscriber.has_service('TRAFFIC'): |
| url = 'http://www.google.com' |
| resp = requests.get(url) |
| self.test_status = resp.ok |
| if resp.ok == False: |
| log_test.info('Subscriber %s failed get from url %s with status code %d' |
| %(subscriber.name, url, resp.status_code)) |
| else: |
| log_test.info('GET request from %s succeeded for subscriber %s' |
| %(url, subscriber.name)) |
| return self.test_status |
| |
| def tls_verify(self, subscriber): |
| if subscriber.has_service('TLS'): |
| time.sleep(2) |
| tls = TLSAuthTest(intf = subscriber.rx_intf) |
| log_test.info('Running subscriber %s tls auth test' %subscriber.name) |
| tls.runTest() |
| self.test_status = True |
| return self.test_status |
| else: |
| self.test_status = True |
| return self.test_status |
| def dhcp_verify(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| cip, sip = self.dhcp_request(subscriber, update_seed = True) |
| log_test.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip)) |
| subscriber.src_list = [cip] |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def dhcp_jump_verify(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| cip, sip = self.dhcp_request(subscriber, seed_ip = '10.10.200.1') |
| log_test.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip)) |
| subscriber.src_list = [cip] |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def dhcp_next_verify(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| cip, sip = self.dhcp_request(subscriber, seed_ip = '10.10.150.1') |
| log_test.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip)) |
| subscriber.src_list = [cip] |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| def igmp_verify(self, subscriber): |
| chan = 0 |
| if subscriber.has_service('IGMP'): |
| ##We wait for all the subscribers to join before triggering leaves |
| if subscriber.rx_port > 1: |
| time.sleep(5) |
| subscriber.channel_join(chan, delay = 0) |
| self.num_joins += 1 |
| while self.num_joins < self.num_subscribers: |
| time.sleep(5) |
| log_test.info('All subscribers have joined the channel') |
| for i in range(10): |
| subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 10) |
| log_test.info('Leaving channel %d for subscriber %s' %(chan, subscriber.name)) |
| subscriber.channel_leave(chan) |
| time.sleep(5) |
| log_test.info('Interface %s Join RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name,subscriber.join_rx_stats)) |
| #Should not receive packets for this subscriber |
| self.recv_timeout = True |
| subscriber.recv_timeout = True |
| subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 10) |
| subscriber.recv_timeout = False |
| self.recv_timeout = False |
| log_test.info('Joining channel %d for subscriber %s' %(chan, subscriber.name)) |
| subscriber.channel_join(chan, delay = 0) |
| self.test_status = True |
| return self.test_status |
| |
| def igmp_jump_verify(self, subscriber): |
| if subscriber.has_service('IGMP'): |
| for i in xrange(subscriber.num): |
| log_test.info('Subscriber %s jumping channel' %subscriber.name) |
| chan = subscriber.channel_jump(delay=0) |
| subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 1) |
| log_test.info('Verified receive for channel %d, subscriber %s' %(chan, subscriber.name)) |
| time.sleep(3) |
| log_test.info('Interface %s Jump RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name, subscriber.join_rx_stats)) |
| self.test_status = True |
| return self.test_status |
| def igmp_next_verify(self, subscriber): |
| if subscriber.has_service('IGMP'): |
| for i in xrange(subscriber.num): |
| if i: |
| chan = subscriber.channel_join_next(delay=0) |
| else: |
| chan = subscriber.channel_join(i, delay=0) |
| log_test.info('Joined next channel %d for subscriber %s' %(chan, subscriber.name)) |
| subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count=1) |
| log_test.info('Verified receive for channel %d, subscriber %s' %(chan, subscriber.name)) |
| time.sleep(3) |
| log_test.info('Interface %s Join Next RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name, subscriber.join_rx_stats)) |
| self.test_status = True |
| return self.test_status |
| |
| def generate_port_list(self, subscribers, channels): |
| return self.port_list[:subscribers] |
| |
| def subscriber_load(self, create = True, num = 10, num_channels = 1, channel_start = 0, port_list = [],controller=None): |
| '''Load the subscriber from the database''' |
| self.subscriber_db = SubscriberDB(create = create, services = self.test_services) |
| if create is True: |
| self.subscriber_db.generate(num) |
| self.subscriber_info = self.subscriber_db.read(num) |
| self.subscriber_list = [] |
| if not port_list: |
| port_list = self.generate_port_list(num, num_channels) |
| |
| index = 0 |
| for info in self.subscriber_info: |
| self.subscriber_list.append(Subscriber(name=info['Name'], |
| service=info['Service'], |
| port_map = self.port_map, |
| num=num_channels, |
| channel_start = channel_start, |
| tx_port = port_list[index][0], |
| rx_port = port_list[index][1])) |
| if num_channels > 1: |
| channel_start += num_channels |
| index += 1 |
| |
| #load the ssm list for all subscriber channels |
| igmpChannel = IgmpChannel(controller=controller) |
| ssm_groups = map(lambda sub: sub.channels, self.subscriber_list) |
| ssm_list = reduce(lambda ssm1, ssm2: ssm1+ssm2, ssm_groups) |
| igmpChannel.igmp_load_ssm_config(ssm_list) |
| def subscriber_join_verify( self, num_subscribers = 10, num_channels = 1, |
| channel_start = 0, cbs = None, port_list = [], negative_subscriber_auth = None,controller=None): |
| log_test.info('controller ip in cluster.py subscriber_join_verify is %s'%controller) |
| self.test_status = False |
| self.ovs_cleanup() |
| subscribers_count = num_subscribers |
| sub_loop_count = num_subscribers |
| self.subscriber_load(create = True, num = num_subscribers, |
| num_channels = num_channels, channel_start = channel_start, port_list = port_list,controller=controller) |
| self.onos_aaa_load(controller=controller) |
| self.thread_pool = ThreadPool(min(100, subscribers_count), queue_size=1, wait_timeout=1) |
| |
| chan_leave = False #for single channel, multiple subscribers |
| if None in (cbs, negative_subscriber_auth): |
| cbs = (self.tls_verify, self.dhcp_verify, self.igmp_verify, self.traffic_verify) |
| chan_leave = True |
| cbs_negative = cbs |
| for subscriber in self.subscriber_list: |
| subscriber.start() |
| if negative_subscriber_auth is 'half' and sub_loop_count%2 is not 0: |
| cbs = (self.tls_verify, self.dhcp_verify, self.igmp_verify, self.traffic_verify) |
| elif negative_subscriber_auth is 'onethird' and sub_loop_count%3 is not 0: |
| cbs = (self.tls_verify, self.dhcp_verify, self.igmp_verify, self.traffic_verify) |
| else: |
| cbs = cbs_negative |
| sub_loop_count = sub_loop_count - 1 |
| pool_object = subscriber_pool(subscriber, cbs) |
| self.thread_pool.addTask(pool_object.pool_cb) |
| self.thread_pool.cleanUpThreads() |
| for subscriber in self.subscriber_list: |
| subscriber.stop() |
| if chan_leave is True: |
| subscriber.channel_leave(0) |
| subscribers_count = 0 |
| return self.test_status |
| def tls_invalid_cert(self, subscriber): |
| if subscriber.has_service('TLS'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s tls auth test' %subscriber.name) |
| tls = TLSAuthTest(client_cert = self.CLIENT_CERT_INVALID) |
| tls.runTest() |
| if tls.failTest == True: |
| self.test_status = False |
| return self.test_status |
| else: |
| self.test_status = True |
| return self.test_status |
| |
| def tls_no_cert(self, subscriber): |
| if subscriber.has_service('TLS'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s tls auth test' %subscriber.name) |
| tls = TLSAuthTest(client_cert = '') |
| tls.runTest() |
| if tls.failTest == True: |
| self.test_status = False |
| return self.test_status |
| else: |
| self.test_status = True |
| return self.test_status |
| |
| def tls_self_signed_cert(self, subscriber): |
| if subscriber.has_service('TLS'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s tls auth test' %subscriber.name) |
| tls = TLSAuthTest(client_cert = self.CLIENT_CERT) |
| tls.runTest() |
| if tls.failTest == False: |
| self.test_status = True |
| return self.test_status |
| else: |
| self.test_status = True |
| return self.test_status |
| |
| def tls_non_ca_authrized_cert(self, subscriber): |
| if subscriber.has_service('TLS'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s tls auth test' %subscriber.name) |
| tls = TLSAuthTest(client_cert = self.CLIENT_CERT_NON_CA_AUTHORIZED) |
| tls.runTest() |
| if tls.failTest == False: |
| self.test_status = True |
| return self.test_status |
| else: |
| self.test_status = True |
| return self.test_status |
| def tls_Nsubscribers_use_same_valid_cert(self, subscriber): |
| if subscriber.has_service('TLS'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s tls auth test' %subscriber.name) |
| num_users = 3 |
| for i in xrange(num_users): |
| tls = TLSAuthTest(intf = 'veth{}'.format(i*2)) |
| tls.runTest() |
| if tls.failTest == False: |
| self.test_status = True |
| return self.test_status |
| else: |
| self.test_status = True |
| return self.test_status |
| |
| def dhcp_discover_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| t1 = self.subscriber_dhcp_1release() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def subscriber_dhcp_1release(self, iface = INTF_RX_DEFAULT): |
| config = {'startip':'10.10.100.20', 'endip':'10.10.100.21', |
| 'ip':'10.10.100.2', 'mac': "ca:fe:ca:fe:8a:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'10.10.100.255', 'router':'10.10.100.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '10.10.100.10', iface = iface) |
| cip, sip = self.send_recv() |
| log_test.info('Releasing ip %s to server %s' %(cip, sip)) |
| assert_equal(self.dhcp.release(cip), True) |
| log_test.info('Triggering DHCP discover again after release') |
| cip2, sip2 = self.send_recv(update_seed = True) |
| log_test.info('Verifying released IP was given back on rediscover') |
| assert_equal(cip, cip2) |
| log_test.info('Test done. Releasing ip %s to server %s' %(cip2, sip2)) |
| assert_equal(self.dhcp.release(cip2), True) |
| def dhcp_client_reboot_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_client_request_after_reboot() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def subscriber_dhcp_client_request_after_reboot(self, iface = INTF_RX_DEFAULT): |
| #''' Client sends DHCP Request after reboot.''' |
| |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.45', iface = iface) |
| cip, sip, mac, lval = self.dhcp.only_discover() |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| |
| log_test.info("Verifying Client 's IP and mac in DHCP Offer packet. Those should not be none, which is expected.") |
| |
| if (cip == None and mac != None): |
| log_test.info("Verified that Client 's IP and mac in DHCP Offer packet are none, which is not expected behavior.") |
| assert_not_equal(cip, None) |
| |
| else: |
| new_cip, new_sip = self.dhcp.only_request(cip, mac) |
| if new_cip == None: |
| log_test.info("Got DHCP server NAK.") |
| os.system('ifconfig '+iface+' down') |
| log_test.info('Client goes down.') |
| log_test.info('Delay for 5 seconds.') |
| |
| time.sleep(5) |
| |
| os.system('ifconfig '+iface+' up') |
| log_test.info('Client is up now.') |
| |
| new_cip, new_sip = self.dhcp.only_request(cip, mac) |
| if new_cip == None: |
| log_test.info("Got DHCP server NAK.") |
| assert_not_equal(new_cip, None) |
| elif new_cip != None: |
| log_test.info("Got DHCP ACK.") |
| def dhcp_client_renew_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_client_renew_time() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def subscriber_dhcp_client_renew_time(self, iface = INTF_RX_DEFAULT): |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.45', iface = iface) |
| cip, sip, mac , lval = self.dhcp.only_discover() |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| |
| log_test.info("Verifying Client 's IP and mac in DHCP Offer packet. Those should not be none, which is expected.") |
| if (cip == None and mac != None): |
| log_test.info("Verified that Client 's IP and mac in DHCP Offer packet are none, which is not expected behavior.") |
| assert_not_equal(cip, None) |
| elif cip and sip and mac: |
| log_test.info("Triggering DHCP Request.") |
| new_cip, new_sip, lval = self.dhcp.only_request(cip, mac, renew_time = True) |
| if new_cip and new_sip and lval: |
| log_test.info("Client 's Renewal time is :%s",lval) |
| log_test.info("Generating delay till renewal time.") |
| time.sleep(lval) |
| log_test.info("Client Sending Unicast DHCP request.") |
| latest_cip, latest_sip = self.dhcp.only_request(new_cip, mac, unicast = True) |
| if latest_cip and latest_sip: |
| log_test.info("Got DHCP Ack. Lease Renewed for ip %s and mac %s from server %s." % |
| (latest_cip, mac, latest_sip) ) |
| |
| elif latest_cip == None: |
| log_test.info("Got DHCP NAK. Lease not renewed.") |
| elif new_cip == None or new_sip == None or lval == None: |
| log_test.info("Got DHCP NAK.") |
| def dhcp_server_reboot_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_server_after_reboot() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| def subscriber_dhcp_server_after_reboot(self, iface = INTF_RX_DEFAULT): |
| ''' DHCP server goes down.''' |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.45', iface = iface) |
| cip, sip, mac, lval = self.dhcp.only_discover() |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| log_test.info("Verifying Client 's IP and mac in DHCP Offer packet. Those should not be none, which is expected.") |
| if (cip == None and mac != None): |
| log_test.info("Verified that Client 's IP and mac in DHCP Offer packet are none, which is not expected behavior.") |
| assert_not_equal(cip, None) |
| else: |
| new_cip, new_sip = self.dhcp.only_request(cip, mac) |
| if new_cip == None: |
| log_test.info("Got DHCP server NAK.") |
| assert_not_equal(new_cip, None) |
| log_test.info('Getting DHCP server Down.') |
| onos_ctrl = OnosCtrl(self.dhcp_app) |
| onos_ctrl.deactivate() |
| for i in range(0,4): |
| log_test.info("Sending DHCP Request.") |
| log_test.info('') |
| new_cip, new_sip = self.dhcp.only_request(cip, mac) |
| if new_cip == None and new_sip == None: |
| log_test.info('') |
| log_test.info("DHCP Request timed out.") |
| elif new_cip and new_sip: |
| log_test.info("Got Reply from DHCP server.") |
| assert_equal(new_cip,None) #Neagtive Test Case |
| log_test.info('Getting DHCP server Up.') |
| # self.activate_apps(self.dhcp_app) |
| onos_ctrl = OnosCtrl(self.dhcp_app) |
| status, _ = onos_ctrl.activate() |
| assert_equal(status, True) |
| time.sleep(3) |
| for i in range(0,4): |
| log_test.info("Sending DHCP Request after DHCP server is up.") |
| log_test.info('') |
| new_cip, new_sip = self.dhcp.only_request(cip, mac) |
| if new_cip == None and new_sip == None: |
| log_test.info('') |
| log_test.info("DHCP Request timed out.") |
| elif new_cip and new_sip: |
| log_test.info("Got Reply from DHCP server.") |
| assert_equal(new_cip,None) #Neagtive Test Case |
| def dhcp_client_rebind_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_client_rebind_time() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def subscriber_dhcp_client_rebind_time(self, iface = INTF_RX_DEFAULT): |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.45', iface = iface) |
| cip, sip, mac, lval = self.dhcp.only_discover() |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| log_test.info("Verifying Client 's IP and mac in DHCP Offer packet. Those should not be none, which is expected.") |
| if (cip == None and mac != None): |
| log_test.info("Verified that Client 's IP and mac in DHCP Offer packet are none, which is not expected behavior.") |
| assert_not_equal(cip, None) |
| elif cip and sip and mac: |
| log_test.info("Triggering DHCP Request.") |
| new_cip, new_sip, lval = self.dhcp.only_request(cip, mac, rebind_time = True) |
| if new_cip and new_sip and lval: |
| log_test.info("Client 's Rebind time is :%s",lval) |
| log_test.info("Generating delay till rebind time.") |
| time.sleep(lval) |
| log_test.info("Client Sending broadcast DHCP requests for renewing lease or for getting new ip.") |
| self.dhcp.after_T2 = True |
| for i in range(0,4): |
| latest_cip, latest_sip = self.dhcp.only_request(new_cip, mac) |
| if latest_cip and latest_sip: |
| log_test.info("Got DHCP Ack. Lease Renewed for ip %s and mac %s from server %s." % |
| (latest_cip, mac, latest_sip) ) |
| break |
| elif latest_cip == None: |
| log_test.info("Got DHCP NAK. Lease not renewed.") |
| assert_not_equal(latest_cip, None) |
| elif new_cip == None or new_sip == None or lval == None: |
| log_test.info("Got DHCP NAK.Lease not Renewed.") |
| def dhcp_starvation_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_starvation() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def subscriber_dhcp_starvation(self, iface = INTF_RX_DEFAULT): |
| '''DHCP starve''' |
| config = {'startip':'182.17.0.20', 'endip':'182.17.0.69', |
| 'ip':'182.17.0.2', 'mac': "ca:fe:c3:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'182.17.0.255', 'router':'182.17.0.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '182.17.0.1', iface = iface) |
| log_test.info('Verifying 1 ') |
| for x in xrange(50): |
| mac = RandMAC()._fix() |
| self.send_recv(mac = mac) |
| log_test.info('Verifying 2 ') |
| cip, sip = self.send_recv(update_seed = True, validate = False) |
| assert_equal(cip, None) |
| assert_equal(sip, None) |
| |
| def dhcp_same_client_multi_discovers_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_same_client_multiple_discover() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| def subscriber_dhcp_same_client_multiple_discover(self, iface = INTF_RX_DEFAULT): |
| ''' DHCP Client sending multiple discover . ''' |
| config = {'startip':'10.10.10.20', 'endip':'10.10.10.69', |
| 'ip':'10.10.10.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'10.10.10.255', 'router':'10.10.10.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '10.10.10.1', iface = iface) |
| cip, sip, mac, lval = self.dhcp.only_discover() |
| log_test.info('Got dhcp client IP %s from server %s for mac %s . Not going to send DHCPREQUEST.' % |
| (cip, sip, mac) ) |
| log_test.info('Triggering DHCP discover again.') |
| new_cip, new_sip, new_mac , lval = self.dhcp.only_discover() |
| if cip == new_cip: |
| log_test.info('Got same ip for 2nd DHCP discover for client IP %s from server %s for mac %s. Triggering DHCP Request. ' |
| % (new_cip, new_sip, new_mac) ) |
| elif cip != new_cip: |
| log_test.info('Ip after 1st discover %s' %cip) |
| log_test.info('Map after 2nd discover %s' %new_cip) |
| assert_equal(cip, new_cip) |
| |
| def dhcp_same_client_multi_request_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_same_client_multiple_request() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| def subscriber_dhcp_same_client_multiple_request(self, iface = INTF_RX_DEFAULT): |
| ''' DHCP Client sending multiple repeat DHCP requests. ''' |
| config = {'startip':'10.10.10.20', 'endip':'10.10.10.69', |
| 'ip':'10.10.10.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'10.10.10.255', 'router':'10.10.10.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '10.10.10.1', iface = iface) |
| log_test.info('Sending DHCP discover and DHCP request.') |
| cip, sip = self.send_recv() |
| mac = self.dhcp.get_mac(cip)[0] |
| log_test.info("Sending DHCP request again.") |
| new_cip, new_sip = self.dhcp.only_request(cip, mac) |
| if (new_cip,new_sip) == (cip,sip): |
| log_test.info('Got same ip for 2nd DHCP Request for client IP %s from server %s for mac %s.' |
| % (new_cip, new_sip, mac) ) |
| elif (new_cip,new_sip): |
| log_test.info('No DHCP ACK') |
| assert_equal(new_cip, None) |
| assert_equal(new_sip, None) |
| else: |
| print "Something went wrong." |
| |
| def dhcp_client_desired_ip_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_client_desired_address() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def subscriber_dhcp_client_desired_address(self, iface = INTF_RX_DEFAULT): |
| '''DHCP Client asking for desired IP address.''' |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.31', iface = iface) |
| cip, sip, mac , lval = self.dhcp.only_discover(desired = True) |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| if cip == self.dhcp.seed_ip: |
| log_test.info('Got dhcp client IP %s from server %s for mac %s as desired .' % |
| (cip, sip, mac) ) |
| elif cip != self.dhcp.seed_ip: |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| log_test.info('The desired ip was: %s .' % self.dhcp.seed_ip) |
| assert_equal(cip, self.dhcp.seed_ip) |
| def dhcp_client_request_pkt_with_non_offered_ip_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_server_nak_packet() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| |
| def subscriber_dhcp_server_nak_packet(self, iface = INTF_RX_DEFAULT): |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.45', iface = iface) |
| cip, sip, mac, lval = self.dhcp.only_discover() |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| log_test.info("Verifying Client 's IP and mac in DHCP Offer packet. Those should not be none, which is expected.") |
| if (cip == None and mac != None): |
| log_test.info("Verified that Client 's IP and mac in DHCP Offer packet are none, which is not expected behavior.") |
| assert_not_equal(cip, None) |
| else: |
| new_cip, new_sip = self.dhcp.only_request('20.20.20.31', mac) |
| if new_cip == None: |
| log_test.info("Got DHCP server NAK.") |
| assert_equal(new_cip, None) #Negative Test Case |
| |
| def dhcp_client_requested_out_pool_ip_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_client_desired_address_out_of_pool() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| def subscriber_dhcp_client_desired_address_out_of_pool(self, iface = INTF_RX_DEFAULT): |
| '''DHCP Client asking for desired IP address from out of pool.''' |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.35', iface = iface) |
| cip, sip, mac, lval = self.dhcp.only_discover(desired = True) |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| if cip == self.dhcp.seed_ip: |
| log_test.info('Got dhcp client IP %s from server %s for mac %s as desired .' % |
| (cip, sip, mac) ) |
| assert_equal(cip, self.dhcp.seed_ip) #Negative Test Case |
| |
| elif cip != self.dhcp.seed_ip: |
| log_test.info('Got dhcp client IP %s from server %s for mac %s .' % |
| (cip, sip, mac) ) |
| log_test.info('The desired ip was: %s .' % self.dhcp.seed_ip) |
| assert_not_equal(cip, self.dhcp.seed_ip) |
| |
| elif cip == None: |
| log_test.info('Got DHCP NAK') |
| |
| def dhcp_client_specific_lease_scenario(self, subscriber): |
| if subscriber.has_service('DHCP'): |
| time.sleep(2) |
| log_test.info('Running subscriber %s DHCP rediscover scenario test' %subscriber.name) |
| tl = self.subscriber_dhcp_specific_lease_packet() |
| self.test_status = True |
| return self.test_status |
| else: |
| subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)] |
| self.test_status = True |
| return self.test_status |
| def subscriber_dhcp_specific_lease_packet(self, iface = INTF_RX_DEFAULT): |
| ''' Client sends DHCP Discover packet for particular lease time.''' |
| config = {'startip':'20.20.20.30', 'endip':'20.20.20.69', |
| 'ip':'20.20.20.2', 'mac': "ca:fe:ca:fe:ca:fe", |
| 'subnet': '255.255.255.0', 'broadcast':'20.20.20.255', 'router':'20.20.20.1'} |
| self.onos_dhcp_table_load(config) |
| self.dhcp = DHCPTest(seed_ip = '20.20.20.45', iface = iface) |
| log_test.info('Sending DHCP discover with lease time of 700') |
| cip, sip, mac, lval = self.dhcp.only_discover(lease_time = True) |
| |
| log_test.info("Verifying Client 's IP and mac in DHCP Offer packet.") |
| if (cip == None and mac != None): |
| log_test.info("Verified that Client 's IP and mac in DHCP Offer packet are none, which is not expected behavior.") |
| assert_not_equal(cip, None) |
| elif lval != 700: |
| log_test.info('Getting dhcp client IP %s from server %s for mac %s with lease time %s. That is not 700.' % |
| (cip, sip, mac, lval) ) |
| assert_not_equal(lval, 700) |