Uploaded image for project: 'netvirt'
  1. netvirt
  2. NETVIRT-892

neutronvpn: support of multiple subnets in one neutron network

    XMLWordPrintable

Details

    • Bug
    • Status: Resolved
    • Medium
    • Resolution: Done
    • Nitrogen
    • Magnesium
    • General
    • None
    • Operating System: All
      Platform: All

    • 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.

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              abhinav.gupta Abhinav Gupta
              valentina.krasnobaeva@6wind.com Valentina Krasnobaeva
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: