[NETVIRT-892] neutronvpn: support of multiple subnets in one neutron network Created: 07/Sep/17  Updated: 25/Nov/19  Resolved: 25/Nov/19

Status: Resolved
Project: netvirt
Component/s: General
Affects Version/s: Nitrogen
Fix Version/s: Magnesium

Type: Bug Priority: Medium
Reporter: Valentina Krasnobaeva Assignee: Abhinav Gupta
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Operating System: All
Platform: All


Issue Links:
Relates
relates to NETVIRT-894 IPV4 address assignment with dhcp is ... Resolved
External issue ID: 9117

 Description   

1. When we add a new subnet B (IPv6) in existed neutron network N with another subnet A (IPv4), we can see following error from NeutronvpnManager.java log:

2017-09-07 15:07:34,951 | ERROR | nPool-1-worker-1 | NeutronvpnManager | 325 - org.opendaylight.netvirt.neutronvpn-impl - 0.6.0.SNAPSHOT | Trying to update non-existing subnetmap node f5f2e500-afad-4944-85c8-6ad8b431fce8

subnet A already existed in network N, when we start to add subnet B => we already have a port X in our network N.

root@controller-deray:~# neutron port-list
------------------------------------------------------------------------------------------------------------------------------------------------------------------+

id name mac_address fixed_ips

------------------------------------------------------------------------------------------------------------------------------------------------------------------+

4adc2a3b-0e6f-4c9a-ad10-cc2dac5bb8a2   fa:16:3e:00:98:c1 {"subnet_id": "bd7ab39a-3d8f-47d7-bc02-88e7b2ea8612", "ip_address": "10.0.0.2"}
      {"subnet_id": "f5f2e500-afad-4944-85c8-6ad8b431fce8", "ip_address": "2001:db8:0:2:f816:3eff:fe00:98c1"}

------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Hence, ODL receives from networking_odl neutron plugin PORT-UPDATE request to update port X with new IPv6 IP --> NeutronPortChangeListener starts to proceed this request and finally calls nvpnManager.updateSubnetmapNodeWithPorts from NeutronvpnManager.

In NeutronvpnManager.updateSubnetmapNodeWithPorts() method we try to obtain Subnetmap object for an already added new IPv6 subnet, but this object still not exist.
So, we pass by "else-condition" from this check "if (sn.isPresent())..", see the method code snippet below:

protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
Subnetmap subnetmap = null;
InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
new SubnetmapKey(subnetId)).build();
try {
synchronized (subnetId.getValue().intern()) {
Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (sn.isPresent()) {
SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
if (null != portId) {
List<Uuid> portList = builder.getPortList();
if (null == portList)

{ portList = new ArrayList<>(); }

portList.add(portId);
builder.setPortList(portList);
LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
portId.getValue());
}
if (null != directPortId) {
List<Uuid> directPortList = builder.getDirectPortList();
if (null == directPortList)

{ directPortList = new ArrayList<>(); }

directPortList.add(directPortId);
builder.setDirectPortList(directPortList);
LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
directPortId.getValue());
}
subnetmap = builder.build();
SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
subnetmap);
} else {
LOG.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
}
}
} catch (Exception e) {
LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
}
return subnetmap;
}

Subnetmap object for already added subnet B doesn't exist, when we proceed PORT-UPDATE, because OpenStack, in this case, sends requests to northbound in the following order:

1. Sending METHOD (put) URL (http://10.100.0.51:8080/controller/nb/v2/neutron/ports/4adc2a3b-0e6f-4c9a-ad10-cc2dac5bb8a2) JSON ({
"port": {
"allowed_address_pairs": [],
"extra_dhcp_opts": [],
"updated_at": "2017-09-07T13:22:09Z",
"device_owner": "network:dhcp",
"revision_number": 16,
"binding:profile": {},
"port_security_enabled": false,
"fixed_ips": [

{ "subnet_id": "bd7ab39a-3d8f-47d7-bc02-88e7b2ea8612", "ip_address": "10.0.0.2" }

,

{ "subnet_id": "596b2a2c-834a-419d-8556-04b788600395", "ip_address": "20.0.0.2" }

,

{ "subnet_id": "1a3d23f3-6d23-4a38-b443-af34e3e83fbb", "ip_address": "2001:db8:0:2:f816:3eff:fe00:98c1" }

],
"security_groups": [],
"binding:vif_details":

{ "port_filter": true }

,
"binding:vif_type": "ovs",
"mac_address": "fa:16:3e:00:98:c1",
"project_id": "25d71d22e2154fbe9e0ac1ecfcfa74c0",
"binding:host_id": "controller-deray",
"description": "",
"device_id": "dhcpf61862b6-e5ad-5e93-972f-a5b392964da5-f0fa945f-2a1f-455c-b25c-53e0f5f13ba1",
"name": "",
"admin_state_up": true,
"created_at": "2017-09-07T13:06:29Z",
"binding:vnic_type": "normal"
}
}) request /opt/stack/networking-odl/networking_odl/common/client.py:86

2. 2017-09-07 15:22:09.985 23981 DEBUG networking_odl.common.client [req-03d36345-c493-4a3f-851a-0bc5fe1761ea admin -] Sending METHOD (post) URL (http://10.100.0.51:8080/controller/nb/v2/neutron/subnets) JSON ({
"subnet": {
"service_types": [],
"description": "",
"enable_dhcp": true,
"network_id": "f0fa945f-2a1f-455c-b25c-53e0f5f13ba1",
"tenant_id": "25d71d22e2154fbe9e0ac1ecfcfa74c0",
"created_at": "2017-09-07T13:22:09Z",
"dns_nameservers": [],
"updated_at": "2017-09-07T13:22:09Z",
"gateway_ip": "2001:db8:0:2::1",
"ipv6_ra_mode": "slaac",
"allocation_pools": [

{ "start": "2001:db8:0:2::2", "end": "2001:db8:0:2:ffff:ffff:ffff:fffe" }

],
"host_routes": [],
"revision_number": 2,
"shared": false,
"ip_version": 6,
"ipv6_address_mode": "slaac",
"cidr": "2001:db8:0:2::/64",
"project_id": "25d71d22e2154fbe9e0ac1ecfcfa74c0",
"id": "1a3d23f3-6d23-4a38-b443-af34e3e83fbb",
"name": "SUB6"
}
}) request /opt/stack/networking-odl/networking_odl/common/client.py:86

So PORT-UPDATE at first and ADD-SUBNET at second, and neutronvpn process them in given order as well. => After updateSubnetmapNodeWithPorts() call, which actually fails, we can see in log createSubnetmapNode() call to create a new SubnetMap.
New Ipv6 Subnetmap is always creating successfully, but it stays not-updated with existed port X. This lies to different connectivity issues, when we test L3 datapath.

2. Steps to reproduce:

neutron net-create A
neutron subnet-create --name SUB4_A A 10.0.0.0/24
openstack subnet create --network A --subnet-range 2001:db8:0:2::/64 SUB6_A --ip-version=6 --ipv6-address-mode=slaac --ipv6-ra-mode=slaac --allocation-pool start=2001:db8:0:2::2,end=2001:db8:0:2:ffff:ffff:ffff:fffe

neutron router-create RT
neutron router-interface-add RT SUB4_A
neutron router-interface-add RT SUB6_A

neutron net-create B

neutron subnet-create --name SUB4_B B 20.0.0.0/24
openstack subnet create --network B --subnet-range 2001:db9:0:3::/64 SUB6_B --ip-version=6 --ipv6-address-mode=slaac --ipv6-ra-mode=slaac --allocation-pool start=2001:db9:0:3::2,end=2001:db9:0:3:ffff:ffff:ffff:fffe

neutron router-interface-add RT SUB4_B
neutron router-interface-add RT SUB6_B

openstack security group rule create X --ingress --dst-port 1:65535 --protocol tcp
openstack security group rule create X --egress --dst-port 1:65535 --protocol tcp
openstack security group rule create X --egress --dst-port 1:65535 --protocol udp
openstack security group rule create X --ingress --dst-port 1:65535 --protocol udp
openstack security group rule create X --ingress --protocol icmp
openstack security group rule create X --egress --protocol icmp
openstack security group rule create X --ingress --ethertype IPv6 --dst-port 1:65535 --protocol tcp
openstack security group rule create X --ingress --ethertype IPv6 --dst-port 1:65535 --protocol udp
openstack security group rule create X --egress --ethertype IPv6 --dst-port 1:65535 --protocol udp
openstack security group rule create X --egress --ethertype IPv6 --dst-port 1:65535 --protocol tcp
openstack security group rule create X --ingress --ethertype IPv6 --protocol icmp
openstack security group rule create X --egress --ethertype IPv6 --protocol icmp

neutron port-create --name PORT1 --security-group X A
openstack server create --image cirros-0.3.4-x86_64-uec --flavor m1.tiny --nic port-id=<PORT1_ID> --security-group X VM1

neutron port-create --name PORT2 --security-group X B
openstack server create --image cirros-0.3.4-x86_64-uec --flavor m1.tiny --nic port-id=<PORT2_ID> --security-group X VM2

Try to ping VM2 by its IPv4 or IPv6 addresses from network's B qdhcp-namespace and vice-versa. This doesn't work sometimes.


Generated at Wed Feb 07 20:22:44 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.