Details
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.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.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": "1a3d23f3-6d23-4a38-b443-af34e3e83fbb", "ip_address": "2001:db8:0:2:f816:3eff:fe00:98c1" } ],
"security_groups": [],
"binding:vif_details":
,
"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": [
],
"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.
Attachments
Issue Links
- relates to
-
NETVIRT-894 IPV4 address assignment with dhcp is not working with dual stack VM.
-
- Resolved
-