Debugging Quantum DHCP and Open vSwitch
This post describes how Quantum DHCP in Grizzly works when using the Open vSwitch plugin. A basic understanding of the mechanism is needed to troubleshoot issues.
There is a common problem where the instance has booted and shows its state to be active, but cannot be pinged or reached with ssh even though security groups allow this traffic. There are many reasons why this might happen, so this post just describes how nova-compute, quantum-openvswitch-plugin-agent and quantum-dhcp-agent setup the connectivity between the instance and dnsmasq that is required for the DHCP packets. It shows what Linux commands can be used and what log files to check.
First verify that the instance did not get an IP address by checking its console log. This can be done from the web dashboard or the nova command and you should see something like this if there was a problem and you are using the cirros test image:
Next you need to find out where the problem is. This is where you need a picture of the all the components involved and how they work together. This will vary depending on which of the following are being used:
This post will provide a working example of one particular configuration: a multinode Grizzy on Ubuntu 12.10, libvirt/QEMU, LibvirtHybridOVSBridgeDriver vif driver, Quantum security groups, Open vSwitch Quantum plugin using GRE, dnsmasq, IP namespaces enabled as setup by the script in this post.
The instance was booted with a nic attached to Quantum network with name net1:
(mistake: I though 172.241.0.0/24 was in RFC1918 - but its not)
After a successful boot, there are four new network devices on the compute node. The first 11 characters of the Quantum port-id are used for naming the network devices associated with it:
Note: 'ip -s link' will show statistics which are useful for troubleshooting. Also note OVS bridges br-int and br-tun are DOWN - this is ok and they should not be put UP.
The LibvirtHybridOVSBridgeDriver plug method running under nova-compute created a Linux bridge named qbr1408934f-93 and plugged the instance's vif (tap1408934f-93) into it. It also created a veth pair qvb1408934f-93 and qvo1408934f-93 to connect the Linux bridge to the OVS bridge br-int. It does all this because OVS and iptables are not compatible when rules are applied directly on vif ports - see limitations at the end of this. Check /var/log/nova/nova-compute.log if there are problems here.
So each port gets its own input and output chains (ending with i1408934f-9 and o1408934f-9). For DHCP the output chain has:
and the input chain has this rule to allow packets from the IP address running the DHCP server (172.241.0.3):
There is also a rule on the output chain to prevent the instance from running a dhcp server on the segment, and rules to prevent the instance spoofing MAC and IP addresses.
If you think there is a problem with iptables, then you can use 'iptables-save -c' to show counters and see which chains are being hit, something like this:
Here the quantum-plugin-openvswitch-agent has put port qvo1408934f-93 into VLAN 2 (tag 2) on br-int. Ports on different Quantum networks will be put in different VLANs for isolation. If the port is not tagged then there is something wrong with the ovs agent - check /var/log/quantum/openvswitch-agent.log. Note: these VLANs are internal to OVS and should not be confused with "real" VLANs from physical switches.
Br-int is connected to br-tun with a patch cable. Br-tun is for inter-connecting data-forwarding nodes (network and compute) using GRE tunnels. Each node will be connected to every other node by a GRE tunnel which results in a full mesh topology. Also br-tun uses MAC flooding and learning to learn which ports the destination MAC addresses of instances are on. Special flows are required to prevent loops as this topology is not loop-free when there are three or more nodes.
Each flow is made up of statistics, a match critera and an action. To map the port numbers to names:
The first flow accepts incoming multicasts (including broadcasts) with GRE key 0x1 (this is the provider:segmentation_id of net1) and tags it for VLAN 2 and send it to br-int via the patch port. There will be one of these flows for each VLAN on br-int.
The second flow is for outgoing traffic from br-int VLAN 2 - it sets the GRE key to 0x1 and gives it the NORMAL action. NORMAL means MAC-learning - so if br-tun does not know which port the destination MAC is on, then it will flood all ports and learn from the source address in reply packets. There will be one of these flows for each VLAN on br-int.
The third flow accepts incoming unicasts with the destination MAC of the instance. There will one of these for each instance running on the compute node.
Any traffic that does not match the first three flows will be dropped by the fourth which has the lowest priority.
The tap device tap9a41d8fa-a7 on br-int is for the DHCP server. Its type is internal which means you can put an IP address on it. Note net1 is given VLAN 1 here - these tags are provisioned locally and may vary for the same network from node to node. The flows in br-tun ensure the translation to and from the segmentation-id in the GRE key field to the local VLAN is correct.
Update: add root_helper = sudo /usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf to workaround this bug.
The agent uses another Quantum port on net1:
The tap device for the DHCP server (dnsmasq) exists within an IP namespace with a name that starts with qdhcp- and ends with the Quantum network-id:
And dnsmasq runs within this IP namespace using this interface:
You should see two copies of the dnsmasq process here. Wait minute and re-run netstat or ps and check that the pid stays the same - there is a bug where dnsmasq continuously respawns sometimes.
The lease time is 120 seconds and if you leave tcpdump running you will see the instance re-up about once per minute (lease time / 2).
The hosts file should contain the MAC/IP pairs for the instances:
Dnsmasq logs to /var/log/syslog in this Ubuntu installation.
The agent communicates with the main Quantum service over rpc. When new ports are added (or removed), the agent updates the host and opts files and sends the dnsmasq the HUP signal which causes it to reload them. This can be be seen in /var/log/quantum/dhcp-agent.log and the syslog.
Then start tcpdump somewhere in the middle and look for the DHCP request and reply packets:
Then depending on what you see, move left or right on diagram tcpdumping on devices until you find where the request or reply packets gets lost. Then check the logs for the agent that should have setup that stage. It might be necessary to restart that agent.
Once the instance gets an IP, you will need to associate a floating IP in order to access it from outside. Or you can use the dhcp namespace on the network node:
There is a common problem where the instance has booted and shows its state to be active, but cannot be pinged or reached with ssh even though security groups allow this traffic. There are many reasons why this might happen, so this post just describes how nova-compute, quantum-openvswitch-plugin-agent and quantum-dhcp-agent setup the connectivity between the instance and dnsmasq that is required for the DHCP packets. It shows what Linux commands can be used and what log files to check.
First verify that the instance did not get an IP address by checking its console log. This can be done from the web dashboard or the nova command and you should see something like this if there was a problem and you are using the cirros test image:
$ nova console-log <instance name or uuid>
...
udhcpc (v1.17.2) started
Sending discover...
Sending discover...
Sending discover...
No lease, forking to background
...
cloud-setup: checking http://169.254.169.254/2009-04-04/meta-data/instance-id
wget: can't connect to remote host (169.254.169.254): Network is unreachable
Next you need to find out where the problem is. This is where you need a picture of the all the components involved and how they work together. This will vary depending on which of the following are being used:
- Hypervisor (KVM, QEMU, etc)
- VIF driver (LibvirtOpenVswitchVirtualPortDriver , LibvirtOpenVswitchDriver, LibvirtHybridOVSBridgeDriver etc)
- Security groups (Nova, Quantum, none)
- Quantum plugin (OVS, Linux bridge etc)
- If OVS plugin, how virtual networks span nodes (GRE, VLAN, flat)
- dhcp_driver (Dnsmasq, etc)
This post will provide a working example of one particular configuration: a multinode Grizzy on Ubuntu 12.10, libvirt/QEMU, LibvirtHybridOVSBridgeDriver vif driver, Quantum security groups, Open vSwitch Quantum plugin using GRE, dnsmasq, IP namespaces enabled as setup by the script in this post.
The instance was booted with a nic attached to Quantum network with name net1:
vagrant@controller:/$ quantum net-show net1
+---------------------------+--------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------+
| admin_state_up | True |
| id | 6b71dbb8-e91c-47f0-92c4-47882007115d |
| name | net1 |
| provider:network_type | gre |
| provider:physical_network | |
| provider:segmentation_id | 1 |
| router:external | False |
| shared | False |
| status | ACTIVE |
| subnets | ad970f3f-4ceb-4565-b897-1cd0fe34cd5b |
| tenant_id | 208914ef96eb492fa3cd066bdcb7bb2b |
+---------------------------+--------------------------------------+
vagrant@controller:/$ quantum subnet-show ad970f3f-4ceb-4565-b897-1cd0fe34cd5b
+------------------+--------------------------------------------------+
| Field | Value |
+------------------+--------------------------------------------------+
| allocation_pools | {"start": "172.241.0.2", "end": "172.241.0.254"} |
| cidr | 172.241.0.0/24 |
| dns_nameservers | |
| enable_dhcp | True |
| gateway_ip | 172.241.0.1 |
| host_routes | |
| id | ad970f3f-4ceb-4565-b897-1cd0fe34cd5b |
| ip_version | 4 |
| name | |
| network_id | 6b71dbb8-e91c-47f0-92c4-47882007115d |
| tenant_id | 208914ef96eb492fa3cd066bdcb7bb2b |
+------------------+--------------------------------------------------+
vagrant@controller:/$ nova boot --flavor micro --image cirros-030-x86_64 \
--nic net-id=6b71dbb8-e91c-47f0-92c4-47882007115d \
--security-groups test-vms test-instance1
...
vagrant@controller:/$ nova list
+--------------------------------------+----------------+--------+------------------+
| ID | Name | Status | Networks |
+--------------------------------------+----------------+--------+------------------+
| 44e362ba-e8a4-4bae-b0ea-5477666632c9 | test-instance1 | ACTIVE | net1=172.241.0.2 |
+--------------------------------------+----------------+--------+------------------+
vagrant@controller:/$ quantum port-list --device_id=44e362ba-e8a4-4bae-b0ea-5477666632c9
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 1408934f-93f9-415c-9c3a-3528f1a1f445 | | fa:16:3e:1e:63:66 | {"subnet_id": "ad970f3f-4ceb-4565-b897-1cd0fe34cd5b", "ip_address": "172.241.0.2"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(mistake: I though 172.241.0.0/24 was in RFC1918 - but its not)
After a successful boot, there are four new network devices on the compute node. The first 11 characters of the Quantum port-id are used for naming the network devices associated with it:
root@compute1:/# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:88:0c:a6 brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:2a:5c:70 brd ff:ff:ff:ff:ff:ff
4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:bc:f6:83 brd ff:ff:ff:ff:ff:ff
5: br-int: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
link/ether e6:1f:7f:53:26:45 brd ff:ff:ff:ff:ff:ff
8: br-tun: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
link/ether 4a:98:b5:e7:ff:41 brd ff:ff:ff:ff:ff:ff
13: qbr1408934f-93: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 22:e3:98:fb:50:8a brd ff:ff:ff:ff:ff:ff
14: qvo1408934f-93: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 0e:ff:72:e2:90:de brd ff:ff:ff:ff:ff:ff
15: qvb1408934f-93: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master qbr1408934f-93 state UP qlen 1000
link/ether 22:e3:98:fb:50:8a brd ff:ff:ff:ff:ff:ff
16: tap1408934f-93: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master qbr1408934f-93 state UNKNOWN qlen 500
link/ether fe:16:3e:1e:63:66 brd ff:ff:ff:ff:ff:ff
Note: 'ip -s link' will show statistics which are useful for troubleshooting. Also note OVS bridges br-int and br-tun are DOWN - this is ok and they should not be put UP.
The LibvirtHybridOVSBridgeDriver plug method running under nova-compute created a Linux bridge named qbr1408934f-93 and plugged the instance's vif (tap1408934f-93) into it. It also created a veth pair qvb1408934f-93 and qvo1408934f-93 to connect the Linux bridge to the OVS bridge br-int. It does all this because OVS and iptables are not compatible when rules are applied directly on vif ports - see limitations at the end of this. Check /var/log/nova/nova-compute.log if there are problems here.
root@compute1:/# brctl show
bridge name bridge id STP enabled interfaces
br-int 0000.e61f7f532645 no qvo1408934f-93
br-tun 0000.4a98b5e7ff41 no
qbr1408934f-93 8000.22e398fb508a no qvb1408934f-93
tap1408934f-93
Iptables
The quantum-plugin-openvswitch-agent configures these on the compute-node to implement the Quantum security groups. The ovs_quantum_plugin.ini has:
And these rules were added:
[SECURITYGROUP]
# Firewall driver for realizing quantum security group function
firewall_driver = quantum.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
root@compute1:/# iptables-save
# Generated by iptables-save v1.4.12 on Wed May 8 14:45:07 2013
*nat
:PREROUTING ACCEPT [19:5732]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [96:5760]
:POSTROUTING ACCEPT [115:11492]
:quantum-openvswi-OUTPUT - [0:0]
:quantum-openvswi-POSTROUTING - [0:0]
:quantum-openvswi-PREROUTING - [0:0]
:quantum-openvswi-float-snat - [0:0]
:quantum-openvswi-snat - [0:0]
:quantum-postrouting-bottom - [0:0]
-A PREROUTING -j quantum-openvswi-PREROUTING
-A OUTPUT -j quantum-openvswi-OUTPUT
-A POSTROUTING -j quantum-openvswi-POSTROUTING
-A POSTROUTING -j quantum-postrouting-bottom
-A quantum-openvswi-snat -j quantum-openvswi-float-snat
-A quantum-postrouting-bottom -j quantum-openvswi-snat
COMMIT
# Completed on Wed May 8 14:45:07 2013
# Generated by iptables-save v1.4.12 on Wed May 8 14:45:07 2013
*filter
:INPUT ACCEPT [5938:1326085]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [7179:1276153]
:quantum-filter-top - [0:0]
:quantum-openvswi-FORWARD - [0:0]
:quantum-openvswi-INPUT - [0:0]
:quantum-openvswi-OUTPUT - [0:0]
:quantum-openvswi-i1408934f-9 - [0:0]
:quantum-openvswi-local - [0:0]
:quantum-openvswi-o1408934f-9 - [0:0]
:quantum-openvswi-sg-chain - [0:0]
:quantum-openvswi-sg-fallback - [0:0]
-A INPUT -j quantum-openvswi-INPUT
-A INPUT -p gre -j ACCEPT
-A FORWARD -j quantum-filter-top
-A FORWARD -j quantum-openvswi-FORWARD
-A OUTPUT -j quantum-filter-top
-A OUTPUT -j quantum-openvswi-OUTPUT
-A quantum-filter-top -j quantum-openvswi-local
-A quantum-openvswi-FORWARD -m physdev --physdev-out tap1408934f-93 --physdev-is-bridged -j quantum-openvswi-sg-chain
-A quantum-openvswi-FORWARD -m physdev --physdev-in tap1408934f-93 --physdev-is-bridged -j quantum-openvswi-sg-chain
-A quantum-openvswi-INPUT -m physdev --physdev-in tap1408934f-93 --physdev-is-bridged -j quantum-openvswi-o1408934f-9
-A quantum-openvswi-i1408934f-9 -m state --state INVALID -j DROP
-A quantum-openvswi-i1408934f-9 -m state --state RELATED,ESTABLISHED -j RETURN
-A quantum-openvswi-i1408934f-9 -p icmp -j RETURN
-A quantum-openvswi-i1408934f-9 -p tcp -m tcp --dport 22 -j RETURN
-A quantum-openvswi-i1408934f-9 -s 172.241.0.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A quantum-openvswi-i1408934f-9 -j quantum-openvswi-sg-fallback
-A quantum-openvswi-o1408934f-9 -m mac ! --mac-source FA:16:3E:1E:63:66 -j DROP
-A quantum-openvswi-o1408934f-9 -p udp -m udp --sport 68 --dport 67 -j RETURN
-A quantum-openvswi-o1408934f-9 ! -s 172.241.0.2/32 -j DROP
-A quantum-openvswi-o1408934f-9 -p udp -m udp --sport 67 --dport 68 -j DROP
-A quantum-openvswi-o1408934f-9 -m state --state INVALID -j DROP
-A quantum-openvswi-o1408934f-9 -m state --state RELATED,ESTABLISHED -j RETURN
-A quantum-openvswi-o1408934f-9 -j RETURN
-A quantum-openvswi-o1408934f-9 -j quantum-openvswi-sg-fallback
-A quantum-openvswi-sg-chain -m physdev --physdev-out tap1408934f-93 --physdev-is-bridged -j quantum-openvswi-i1408934f-9
-A quantum-openvswi-sg-chain -m physdev --physdev-in tap1408934f-93 --physdev-is-bridged -j quantum-openvswi-o1408934f-9
-A quantum-openvswi-sg-chain -j ACCEPT
-A quantum-openvswi-sg-fallback -j DROP
COMMIT
So each port gets its own input and output chains (ending with i1408934f-9 and o1408934f-9). For DHCP the output chain has:
-A quantum-openvswi-o1408934f-9 -p udp -m udp --sport 68 --dport 67 -j RETURN
and the input chain has this rule to allow packets from the IP address running the DHCP server (172.241.0.3):
-A quantum-openvswi-i1408934f-9 -s 172.241.0.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
There is also a rule on the output chain to prevent the instance from running a dhcp server on the segment, and rules to prevent the instance spoofing MAC and IP addresses.
If you think there is a problem with iptables, then you can use 'iptables-save -c' to show counters and see which chains are being hit, something like this:
iptables-save -c >/tmp/sample1
# make the instance do a dhcp request
iptables-save -c >/tmp/sample2
diff /tmp/sample1 /tmp/sample2
Open vSwitch on the compute-node
There are two OVS bridges on the compute-node. Br-int is for connecting instances (indirectly with the hybrid vif driver) and br-tun for connecting physical nodes when using GRE mode.
root@compute1:/# ovs-vsctl show
3f7c02b4-00d2-4b4e-871d-eafdc22eb67b
Bridge br-int
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port br-int
Interface br-int
type: internal
Port "qvo1408934f-93"
tag: 2
Interface "qvo1408934f-93"
Bridge br-tun
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Port "gre-1"
Interface "gre-1"
type: gre
options: {in_key=flow, out_key=flow, remote_ip="10.0.20.11"}
ovs_version: "1.4.0+build0"
Here the quantum-plugin-openvswitch-agent has put port qvo1408934f-93 into VLAN 2 (tag 2) on br-int. Ports on different Quantum networks will be put in different VLANs for isolation. If the port is not tagged then there is something wrong with the ovs agent - check /var/log/quantum/openvswitch-agent.log. Note: these VLANs are internal to OVS and should not be confused with "real" VLANs from physical switches.
Br-int is connected to br-tun with a patch cable. Br-tun is for inter-connecting data-forwarding nodes (network and compute) using GRE tunnels. Each node will be connected to every other node by a GRE tunnel which results in a full mesh topology. Also br-tun uses MAC flooding and learning to learn which ports the destination MAC addresses of instances are on. Special flows are required to prevent loops as this topology is not loop-free when there are three or more nodes.
root@compute1:/# ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=6845.074s, table=0, n_packets=55, n_bytes=4950, priority=3,tun_id=0x1,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=mod_vlan_vid:2,output:1
cookie=0x0, duration=6845.411s, table=0, n_packets=772, n_bytes=172410, priority=4,in_port=1,dl_vlan=2 actions=set_tunnel:0x1,NORMAL
cookie=0x0, duration=6844.75s, table=0, n_packets=182, n_bytes=46000, priority=3,tun_id=0x1,dl_dst=fa:16:3e:1e:63:66 actions=mod_vlan_vid:2,NORMAL
cookie=0x0, duration=10496.078s, table=0, n_packets=13, n_bytes=974, priority=1 actions=drop
Each flow is made up of statistics, a match critera and an action. To map the port numbers to names:
root@compute1:/# ovs-ofctl show br-tun | grep '^ [0-9]'
1(patch-int): addr:22:29:a4:f9:45:8b
2(gre-1): addr:ce:d9:0a:15:d8:2c
The first flow accepts incoming multicasts (including broadcasts) with GRE key 0x1 (this is the provider:segmentation_id of net1) and tags it for VLAN 2 and send it to br-int via the patch port. There will be one of these flows for each VLAN on br-int.
The second flow is for outgoing traffic from br-int VLAN 2 - it sets the GRE key to 0x1 and gives it the NORMAL action. NORMAL means MAC-learning - so if br-tun does not know which port the destination MAC is on, then it will flood all ports and learn from the source address in reply packets. There will be one of these flows for each VLAN on br-int.
The third flow accepts incoming unicasts with the destination MAC of the instance. There will one of these for each instance running on the compute node.
Any traffic that does not match the first three flows will be dropped by the fourth which has the lowest priority.
Open vSwitch on the network node
This is very similar to the compute-node. The quantum-dhcp-agent created a tap interface plugged into br-int.
root@netnode:/# ovs-vsctl show
20f4084e-0758-41bd-8dfe-5f54883c28e0
Bridge br-ex
Port "qg-dff8f187-92"
Interface "qg-dff8f187-92"
type: internal
Port br-ex
Interface br-ex
type: internal
Port "eth3"
Interface "eth3"
Bridge br-int
Port "tap9a41d8fa-a7"
tag: 1
Interface "tap9a41d8fa-a7"
type: internal
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port br-int
Interface br-int
type: internal
Bridge br-tun
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Port "gre-2"
Interface "gre-2"
type: gre
options: {in_key=flow, out_key=flow, remote_ip="10.0.20.12"}
ovs_version: "1.4.0+build0"
root@netnode:/# ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=16029.492s, table=0, n_packets=1465, n_bytes=382914, priority=3,tun_id=0x1,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=mod_vlan_vid:1,output:1
cookie=0x0, duration=16029.712s, table=0, n_packets=534, n_bytes=115374, priority=4,in_port=1,dl_vlan=1 actions=set_tunnel:0x1,NORMAL
cookie=0x0, duration=2.16s, table=0, n_packets=0, n_bytes=0, priority=3,tun_id=0x1,dl_dst=fa:16:3e:27:d6:30 actions=mod_vlan_vid:1,NORMAL
cookie=0x0, duration=17440.954s, table=0, n_packets=26, n_bytes=2720, priority=1 actions=drop
The tap device tap9a41d8fa-a7 on br-int is for the DHCP server. Its type is internal which means you can put an IP address on it. Note net1 is given VLAN 1 here - these tags are provisioned locally and may vary for the same network from node to node. The flows in br-tun ensure the translation to and from the segmentation-id in the GRE key field to the local VLAN is correct.
The DHCP agent
The DHCP agent is configured to use OVS and dnsmasq:root@netnode:/# grep -v '^#\|^\s*$' /etc/quantum/dhcp_agent.ini
[DEFAULT]
interface_driver = quantum.agent.linux.interface.OVSInterfaceDriver
dhcp_driver = quantum.agent.linux.dhcp.Dnsmasq
Update: add root_helper = sudo /usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf to workaround this bug.
The agent uses another Quantum port on net1:
vagrant@controller:/$ quantum port-show 9a41d8fa-a745-4411-b9f8-daa182f38527
+----------------------+------------------------------------------------------------------------------------+
| Field | Value |
+----------------------+------------------------------------------------------------------------------------+
| admin_state_up | True |
| binding:capabilities | {"port_filter": true} |
| binding:vif_type | ovs |
| device_id | dhcpa01fb276-fc1a-5a98-90b4-3413b63a3276-6b71dbb8-e91c-47f0-92c4-47882007115d |
| device_owner | network:dhcp |
| fixed_ips | {"subnet_id": "ad970f3f-4ceb-4565-b897-1cd0fe34cd5b", "ip_address": "172.241.0.3"} |
| id | 9a41d8fa-a745-4411-b9f8-daa182f38527 |
| mac_address | fa:16:3e:27:d6:30 |
| name | |
| network_id | 6b71dbb8-e91c-47f0-92c4-47882007115d |
| security_groups | |
| status | ACTIVE |
| tenant_id | 208914ef96eb492fa3cd066bdcb7bb2b |
+----------------------+------------------------------------------------------------------------------------+
The tap device for the DHCP server (dnsmasq) exists within an IP namespace with a name that starts with qdhcp- and ends with the Quantum network-id:
root@netnode:/# ip netns | grep dhcp
qdhcp-6b71dbb8-e91c-47f0-92c4-47882007115d
root@netnode:/# ip netns exec qdhcp-6b71dbb8-e91c-47f0-92c4-47882007115d ip address
13: tap9a41d8fa-a7: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether fa:16:3e:27:d6:30 brd ff:ff:ff:ff:ff:ff
inet 172.241.0.3/24 brd 172.241.0.255 scope global tap9a41d8fa-a7
inet6 fe80::f816:3eff:fe27:d630/64 scope link
valid_lft forever preferred_lft forever
14: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
And dnsmasq runs within this IP namespace using this interface:
root@netnode:/# ip netns exec qdhcp-6b71dbb8-e91c-47f0-92c4-47882007115d netstat -pan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 172.241.0.3:53 0.0.0.0:* LISTEN 8920/dnsmasq
tcp6 0 0 fe80::f816:3eff:fe27:53 :::* LISTEN 8920/dnsmasq
udp 0 0 172.241.0.3:53 0.0.0.0:* 8920/dnsmasq
udp 0 0 0.0.0.0:67 0.0.0.0:* 8920/dnsmasq
udp6 0 0 fe80::f816:3eff:fe27:53 :::* 8920/dnsmasq
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node PID/Program name Path
unix 2 [ ] DGRAM 3170559 8920/dnsmasq
root@netnode:/# ps -ef | grep 8920
nobody 8920 1 0 19:15 ? 00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap9a41d8fa-a7 --except-interface=lo --pid-file=/var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/pid --dhcp-hostsfile=/var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/host --dhcp-optsfile=/var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/opts --dhcp-script=/usr/bin/quantum-dhcp-agent-dnsmasq-lease-update --leasefile-ro --dhcp-range=set:tag0,172.241.0.0,static,120s --conf-file= --domain=openstacklocal
root 8921 8920 0 19:15 ? 00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap9a41d8fa-a7 --except-interface=lo --pid-file=/var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/pid --dhcp-hostsfile=/var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/host --dhcp-optsfile=/var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/opts --dhcp-script=/usr/bin/quantum-dhcp-agent-dnsmasq-lease-update --leasefile-ro --dhcp-range=set:tag0,172.241.0.0,static,120s --conf-file= --domain=openstacklocal
root 25444 1618 0 19:33 pts/2 00:00:00 grep --color=auto 8920
You should see two copies of the dnsmasq process here. Wait minute and re-run netstat or ps and check that the pid stays the same - there is a bug where dnsmasq continuously respawns sometimes.
The lease time is 120 seconds and if you leave tcpdump running you will see the instance re-up about once per minute (lease time / 2).
The hosts file should contain the MAC/IP pairs for the instances:
root@netnode:/# cat /var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/host
fa:16:3e:1e:63:66,172-241-0-2.openstacklocal,172.241.0.2
fa:16:3e:27:d6:30,172-241-0-3.openstacklocal,172.241.0.3
Dnsmasq logs to /var/log/syslog in this Ubuntu installation.
May 8 19:15:54 netnode dnsmasq[8920]: started, version 2.59 cachesize 150
May 8 19:15:54 netnode dnsmasq[8920]: compile time options: IPv6 GNU-getopt DBus i18n DHCP TFTP conntrack IDN
May 8 19:15:54 netnode dnsmasq[8920]: warning: no upstream servers configured
May 8 19:15:54 netnode dnsmasq-dhcp[8920]: DHCP, static leases only on 172.241.0.0, lease time 2m
May 8 19:15:54 netnode dnsmasq[8920]: cleared cache
May 8 19:15:54 netnode dnsmasq-dhcp[8920]: read /var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/host
May 8 19:15:54 netnode dnsmasq-dhcp[8920]: read /var/lib/quantum/dhcp/6b71dbb8-e91c-47f0-92c4-47882007115d/opts
May 8 19:17:23 netnode dnsmasq-dhcp[8920]: DHCPDISCOVER(tap9a41d8fa-a7) 172.241.0.2 fa:16:3e:1e:63:66
May 8 19:17:23 netnode dnsmasq-dhcp[8920]: DHCPOFFER(tap9a41d8fa-a7) 172.241.0.2 fa:16:3e:1e:63:66
May 8 19:17:23 netnode dnsmasq-dhcp[8920]: DHCPREQUEST(tap9a41d8fa-a7) 172.241.0.2 fa:16:3e:1e:63:66
May 8 19:17:23 netnode dnsmasq-dhcp[8920]: DHCPACK(tap9a41d8fa-a7) 172.241.0.2 fa:16:3e:1e:63:66 172-241-0-2
The agent communicates with the main Quantum service over rpc. When new ports are added (or removed), the agent updates the host and opts files and sends the dnsmasq the HUP signal which causes it to reload them. This can be be seen in /var/log/quantum/dhcp-agent.log and the syslog.
Debugging with tcpdump
If the instance does not have an IP yet, you can still access it using vnc from the web dashboard. If using the cirros test image, do 'sudo udhcpc' and it will a send dhcp request about once per second until it gets a reply.Then start tcpdump somewhere in the middle and look for the DHCP request and reply packets:
root@compute1:/# tcpdump -n -i eth2 | grep -v IP6
...
14:30:53.389538 IP 10.0.20.12 > 10.0.20.11: GREv0, key=0x1, length 334: IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from fa:16:3e:1e:63:66, length 280
14:30:53.409163 IP 10.0.20.11 > 10.0.20.12: GREv0, key=0x1, length 375: IP 172.241.0.3.67 > 172.241.0.2.68: BOOTP/DHCP, Reply, length 321
Then depending on what you see, move left or right on diagram tcpdumping on devices until you find where the request or reply packets gets lost. Then check the logs for the agent that should have setup that stage. It might be necessary to restart that agent.
Once the instance gets an IP, you will need to associate a floating IP in order to access it from outside. Or you can use the dhcp namespace on the network node:
root@netnode:/# ip netns exec qdhcp-6b71dbb8-e91c-47f0-92c4-47882007115d ssh cirros@172.241.0.2