IPV6 changes for VMTP

Change-Id: I4958a119ff9dff661fb04f1973d76c4c3ee645f8
This commit is contained in:
AJAY KALAMBUR 2015-02-25 12:43:33 -08:00
parent cfb6c1fc19
commit 411e3dac2e
8 changed files with 136 additions and 22 deletions

View File

@ -68,6 +68,14 @@ reuse_existing_vm :
# An option of config_drive to True is provided to nova boot to enable this
config_drive:
# ipv6 mode. Set this to one of the following 3 modes
# slaac : VM obtains IPV6 address from Openstack radvd using SLAAC
# dhcpv6-stateful : VM obtains ipv6 address from dnsmasq using DHCPv6 stateful
# dhcpv6-stateless : VM obtains ipv6 address from Openstack radvd using SLAAC and options from dnsmasq
# If left blank use ipv4
ipv6_mode:
# Default name for the router to use to connect the internal mgmt network
# with the external network. If a router exists with this name it will be
# reused, otherwise a new router will be created
@ -82,9 +90,15 @@ internal_network_name: ['pns-internal-net', 'pns-internal-net2']
# Name of the subnets associated to the internal mgmt network
internal_subnet_name: ['pns-internal-subnet', 'pns-internal-subnet2']
# Name of the subnets for ipv6
internal_subnet_name_ipv6: ['pns-internal-v6-subnet','pns-internal-v6-subnet2']
# Default CIDRs to use for the internal mgmt subnet
internal_cidr: ['192.168.1.0/24' , '192.168.2.0/24']
# Default CIDRs to use for data network for ipv6
internal_cidr_v6: ['2001:45::/64','2001:46::/64']
# The public key to use to ssh to all targets (VMs, containers, hosts)
# If starting with './' is relative to the location of the VMTP script
# else can be an absolute path

View File

@ -395,6 +395,12 @@ class Compute(object):
ip_protocol="icmp",
from_port=-1,
to_port=-1)
if self.config.ipv6_mode:
self.novaclient.security_group_rules.create(group.id,
ip_protocol="icmp",
from_port=-1,
to_port=-1,
cidr="::/0")
# Allow SSH traffic
self.novaclient.security_group_rules.create(group.id,
ip_protocol="tcp",
@ -404,11 +410,24 @@ class Compute(object):
# 5001: Data traffic (standard iperf data port)
# 5002: Control traffic (non standard)
# note that 5000/tcp is already picked by openstack keystone
self.novaclient.security_group_rules.create(group.id,
ip_protocol="tcp",
from_port=5001,
to_port=5002)
self.novaclient.security_group_rules.create(group.id,
ip_protocol="udp",
from_port=5001,
to_port=5001)
if not self.config.ipv6_mode:
self.novaclient.security_group_rules.create(group.id,
ip_protocol="tcp",
from_port=5001,
to_port=5002)
self.novaclient.security_group_rules.create(group.id,
ip_protocol="udp",
from_port=5001,
to_port=5001)
else:
# IPV6 rules addition
self.novaclient.security_group_rules.create(group.id,
ip_protocol="tcp",
from_port=5001,
to_port=5002,
cidr="::/0")
self.novaclient.security_group_rules.create(group.id,
ip_protocol="udp",
from_port=5001,
to_port=5001,
cidr="::/0")

View File

@ -241,3 +241,14 @@ The first IP passed (*--host*) is always the one running the server side. Option
**Note:** Prior to running, the VMTP public key must be installed on each VM.
Example 7: IPV6 throughput measurement
""""""""""""""""""""""""""""""""""""""""
It is possible to use VMTP to measure throughput for ipv6
Set ipv6_mode to slaac, dhcpv6-stateful or dhcpv6-stateless. If SLAAC or DHCPv6 stateless is enabled make sure to have
radvd packaged in as part of openstack install. For DHCPv6 stateful you need dnsmasq version >= 2.68. The test creates
2 networks and creates 1 ipv4 and 1 ipv6 subnet inside each of these networks. The subnets are created based on the ipv6
mode that you set in the configuration file. The floatingip result case is skipped for ipv6 since there is no concept of
a floating ip with ipv6.

View File

@ -18,9 +18,12 @@ import re
import stat
import subprocess
import monitor
import sshutils
from netaddr import IPAddress
# a dictionary of sequence number indexed by a name prefix
prefix_seq = {}
@ -108,7 +111,20 @@ class Instance(object):
# Assume management network has direct access
if self.config.reuse_network_name:
self.ssh_ip = self.instance.networks[internal_network_name][0]
self.internal_ip = self.ssh_ip
else:
# Set the internal ip to the correct ip for v4 and v6
for ip_address in self.instance.networks[internal_network_name]:
ip = IPAddress(ip_address)
if self.config.ipv6_mode:
if ip.version == 6:
self.internal_ip = ip_address
else:
ipv4_fixed_address = ip_address
else:
if ip.version == 4:
self.internal_ip = ip_address
ipv4_fixed_address = ip_address
fip = self.net.create_floating_ip()
if not fip:
self.display('Floating ip creation failed')
@ -117,9 +133,8 @@ class Instance(object):
self.ssh_ip_id = fip['floatingip']['id']
self.buginf('Floating IP %s created', self.ssh_ip)
self.buginf('Started - associating floating IP %s', self.ssh_ip)
self.instance.add_floating_ip(self.ssh_ip)
self.instance.add_floating_ip(self.ssh_ip, ipv4_fixed_address)
# extract the IP for the data network
self.internal_ip = self.instance.networks[internal_network_name][0]
self.buginf('Internal network IP: %s', self.internal_ip)
self.buginf('SSH IP: %s', self.ssh_ip)

View File

@ -40,6 +40,8 @@ class Network(object):
# - second for network to network communication
self.vm_int_net = []
self.ext_router_name = None
# Store state if the network is ipv4/ipv6 dual stack
self.ipv6_enabled = False
# If reusing existing management network just find this network
if self.config.reuse_network_name:
@ -94,13 +96,27 @@ class Network(object):
print '[%s] Created ext router' % (self.ext_router_name)
self.ext_router_created = True
# Create the 2 internal networks
for (net, subnet, cidr) in zip(config.internal_network_name,
config.internal_subnet_name,
config.internal_cidr):
int_net = self.create_net(net, subnet, cidr,
config.dns_nameservers)
self.vm_int_net.append(int_net)
if config.ipv6_mode:
self.ipv6_enabled = True
# Create the networks and subnets depending on v4 or v6
if config.ipv6_mode:
for (net, subnet, cidr, subnet_ipv6, cidr_ipv6) in zip(config.internal_network_name,
config.internal_subnet_name,
config.internal_cidr,
config.internal_subnet_name_ipv6,
config.internal_cidr_v6):
int_net = self.create_net(net, subnet, cidr,
config.dns_nameservers,
subnet_ipv6, cidr_ipv6, config.ipv6_mode)
self.vm_int_net.append(int_net)
else:
for (net, subnet, cidr) in zip(config.internal_network_name,
config.internal_subnet_name,
config.internal_cidr):
int_net = self.create_net(net, subnet, cidr,
config.dns_nameservers)
self.vm_int_net.append(int_net)
# Add both internal networks to router interface to enable network to network connectivity
self.__add_router_interface()
@ -109,7 +125,8 @@ class Network(object):
# Check first if a network with the same name exists, if it exists
# return that network.
# dns_nameservers: a list of name servers e.g. ['8.8.8.8']
def create_net(self, network_name, subnet_name, cidr, dns_nameservers):
def create_net(self, network_name, subnet_name, cidr, dns_nameservers,
subnet_name_ipv6=None, cidr_ipv6=None, ipv6_mode=None):
for network in self.networks:
if network['name'] == network_name:
@ -137,6 +154,22 @@ class Network(object):
subnet = self.neutron_client.create_subnet(body)['subnet']
# add subnet id to the network dict since it has just been added
network['subnets'] = [subnet['id']]
# If ipv6 is enabled than create and add ipv6 network
if ipv6_mode:
body = {
'subnet': {
'name': subnet_name_ipv6,
'cidr': cidr_ipv6,
'network_id': network['id'],
'enable_dhcp': True,
'ip_version': 6,
'ipv6_ra_mode': ipv6_mode,
'ipv6_address_mode': ipv6_mode
}
}
subnet = self.neutron_client.create_subnet(body)['subnet']
# add the subnet id to the network dict
network['subnets'].append(subnet['id'])
print 'Created internal network: %s' % (network_name)
return network
@ -180,11 +213,24 @@ class Network(object):
self.neutron_client.add_interface_router(self.ext_router['id'], body)
if self.config.debug:
print 'Ext router associated to ' + int_net['name']
# If ipv6 is enabled than add second subnet
if self.ipv6_enabled:
body = {
'subnet_id': int_net['subnets'][1]
}
self.neutron_client.add_interface_router(self.ext_router['id'], body)
# Detach the ext router from the mgmt network
def __remove_router_interface(self):
for int_net in self.vm_int_net:
if int_net:
# If ipv6 is enabled remove that subnet too
if self.ipv6_enabled:
body = {
'subnet_id': int_net['subnets'][1]
}
self.neutron_client.remove_interface_router(self.ext_router['id'],
body)
body = {
'subnet_id': int_net['subnets'][0]
}

View File

@ -25,7 +25,10 @@ class NuttcpTool(PerfTool):
def get_server_launch_cmd(self):
'''Return the commands to launch the server side.'''
return [self.dest_path + ' -P5002 -S --single-threaded &']
if self.instance.config.ipv6_mode:
return [self.dest_path + ' -P5002 -S --single-threaded -6 &']
else:
return [self.dest_path + ' -P5002 -S --single-threaded &']
def run_client(self, target_ip, target_instance,
mss=None, bandwidth=0, bidirectional=False):
@ -117,6 +120,8 @@ class NuttcpTool(PerfTool):
opts += " -F -r"
if length:
opts += " -l" + str(length)
if self.instance.config.ipv6_mode:
opts += " -6 "
if udp:
opts += " -u"
# for UDP if the bandwidth is not provided we need to calculate

View File

@ -238,7 +238,10 @@ class PingTool(PerfTool):
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.455/0.528/0.596/0.057 ms
'''
cmd = "ping -c " + str(ping_count) + " " + str(target_ip)
if self.instance.config.ipv6_mode:
cmd = "ping6 -c " + str(ping_count) + " " + str(target_ip)
else:
cmd = "ping -c " + str(ping_count) + " " + str(target_ip)
cmd_out = self.instance.exec_command(cmd)
if not cmd_out:
res = {'protocol': 'ICMP',

View File

@ -364,8 +364,9 @@ class VmtpTest(object):
self.measure_flow("VM to VM different network fixed IP",
self.server.internal_ip)
self.measure_flow("VM to VM different network floating IP",
self.server.ssh_ip)
if not config.ipv6_mode:
self.measure_flow("VM to VM different network floating IP",
self.server.ssh_ip)
self.client.dispose()
self.client = None