Bug 1689368 - OVN replying with unsolicited DHCP options
Summary: OVN replying with unsolicited DHCP options
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Red Hat Enterprise Linux Fast Datapath
Classification: Red Hat
Component: OVN
Version: FDP 19.C
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
: ---
Assignee: Open vSwitch development team
QA Contact: haidong li
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2019-03-15 17:53 UTC by Carlos Goncalves
Modified: 2019-03-28 15:16 UTC (History)
9 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-03-27 12:20:21 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)

Description Carlos Goncalves 2019-03-15 17:53:03 UTC
Created a network and subnet with gateway enabled (via Neutron ML2/OVN). DHCP client requests specific options which do not include default gateway, yet DHCP server replies with Default-Gateway and 169.254.169.254 route.

$ ip r
default via 192.168.121.1 dev eth0 proto dhcp metric 100 
172.24.4.0/24 dev br-ex proto kernel scope link src 172.24.4.1 
192.168.121.0/24 dev eth0 proto kernel scope link src 192.168.121.91 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

$ sudo cat /etc/dhcp/octavia/dhclient.conf
request subnet-mask,broadcast-address,interface-mtu;
do-forward-updates false;

$ sudo dhclient -v o-hm0 -cf /etc/dhcp/octavia/dhclient.conf
Internet Systems Consortium DHCP Client 4.2.5
Copyright 2004-2013 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/o-hm0/fa:16:3e:98:ef:c9
Sending on   LPF/o-hm0/fa:16:3e:98:ef:c9
Sending on   Socket/fallback
DHCPREQUEST on o-hm0 to 255.255.255.255 port 67 (xid=0x8e98cc2)
DHCPACK from 192.168.0.1 (xid=0x8e98cc2)
bound to 192.168.0.50 -- renewal in 19243 seconds.

$ sudo tcpdump -n -vvv -i o-hm0
tcpdump: listening on o-hm0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:15:14.649546 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
    0.0.0.0.bootpc > 255.255.255.255.bootps: [udp sum ok] BOOTP/DHCP, Request from fa:16:3e:98:ef:c9, length 300, xid 0xc28ce908, Flags [none] (0x0000)
          Client-Ethernet-Address fa:16:3e:98:ef:c9
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Request
            Requested-IP Option 50, length 4: 192.168.0.50
            Parameter-Request Option 55, length 3:
              Subnet-Mask, BR, MTU
            END Option 255, length 0
            PAD Option 0, length 0, occurs 45
17:15:14.653748 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 330)
    192.168.0.1.bootps > 192.168.0.50.bootpc: [no cksum] BOOTP/DHCP, Reply, length 302, xid 0xc28ce908, Flags [none] (0x0000)
          Your-IP 192.168.0.50
          Client-Ethernet-Address fa:16:3e:98:ef:c9
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: ACK
            Classless-Static-Route Option 121, length 14: (169.254.169.254/32:192.168.0.2),(default:192.168.0.1)
            Domain-Name-Server Option 6, length 4: 192.168.121.1
            Lease-Time Option 51, length 4: 43200
            MTU Option 26, length 2: 1442
            Subnet-Mask Option 1, length 4: 255.255.255.0
            Default-Gateway Option 3, length 4: 192.168.0.1
            Server-ID Option 54, length 4: 192.168.0.1
            PAD Option 0, length 0, occurs 4
            END Option 255, length 0
            PAD Option 0, length 0, occurs 4
17:15:14.736486 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 192.168.0.50 (Broadcast) tell 0.0.0.0, length 28
17:15:15.736646 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 192.168.0.50 (Broadcast) tell 0.0.0.0, length 28


$ ip r
default via 192.168.0.1 dev o-hm0 
default via 192.168.121.1 dev eth0 proto dhcp metric 100 
169.254.169.254 via 192.168.0.2 dev o-hm0 proto static 
172.24.4.0/24 dev br-ex proto kernel scope link src 172.24.4.1 
192.168.0.0/24 dev o-hm0 proto kernel scope link src 192.168.0.50 
192.168.121.0/24 dev eth0 proto kernel scope link src 192.168.121.91 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

$ ovs-vsctl --version
ovs-vsctl (Open vSwitch) 2.11.90
DB Schema 8.0.0

Comment 2 Numan Siddique 2019-03-15 18:54:04 UTC
Hi Carlos,
The native OVN DHCP responder is kind of a dump server which replies with the options defined in the DHC_Options Northbound table.

Is this creating any issues ? We could fix it, but it requires local ovn-controller to look for the dhcp options in the request and include only those.
I need to check the DHCP RFC, but is it mandatory for DHCP server to not include other options (not requested by the client) ?

Thanks
Numan

Comment 3 Carlos Goncalves 2019-03-15 22:28:33 UTC
It is adding a L3 gateway (default via 192.168.0.1 dev o-hm0) to the routing table which conflicts with the existing one and thus starts routing traffic via an undesired device. It also adds a new route to 169.254.169.254 via 192.168.0.2 which could potentially conflict with existing routing rules -- it is not the case here but could have been.

From https://tools.ietf.org/html/rfc2132:


   9.8. Parameter Request List

   This option is used by a DHCP client to request values for specified
   configuration parameters.  The list of requested parameters is
   specified as n octets, where each octet is a valid DHCP option code
   as defined in this document.

   The client MAY list the options in order of preference.  The DHCP
   server is not required to return the options in the requested order,
   but MUST try to insert the requested options in the order requested
   by the client.

Comment 4 qding 2019-03-18 00:20:46 UTC
Take

Comment 5 Numan Siddique 2019-03-18 05:35:35 UTC
I think this can be easily handled in networking-ovn.
It needs to create a new DHCP_Options row and remove the default route from the dhcp options.

@Daniel - Any comments on this ?

Comment 6 Daniel Alvarez Sanchez 2019-03-18 07:31:00 UTC
Hi :)

@Numan, for the specific case of Octavia it may be possible although we would need Carlos to confirm as I don't know the specifics of that network (ie. is there any other ports in that network which would require the gateway?). This IMO would be a workaround but a possible one.

About the general case I think that we need to address it in ovn-controller and honour the requested parameters by the client. Note, that this is *per port* so one client in the same logical switch can request something and another client can request some other thing. Most importantly, the same client could request a different set of parameters later on.

What do you think?

Comment 7 Numan Siddique 2019-03-18 09:34:56 UTC
Few points
 -  ovn-controller dhcp "responder" is not a full fledged server 
 -  It is  mostly a dumb dhcp responder, which responds with the options defined in the Northbound "DHCP_Options' table.
 - the dhcp response is expressed as logical flows - like 

Right now the logical flows would look like

****
 table=12(ls_in_dhcp_options ), priority=100  , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 192.168.0.2, lease_time = 3600, netmask = 255.255.255.0, server_id = 192.168.0.1); next;)
  table=12(ls_in_dhcp_options ), priority=100  , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 192.168.0.2 && ip4.dst == {192.168.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 192.168.0.2, lease_time = 3600, netmask = 255.255.255.0, server_id = 192.168.0.1); next;)
  table=12(ls_in_dhcp_options ), priority=0    , match=(1), action=(next;)
  table=13(ls_in_dhcp_response), priority=100  , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3]), action=(eth.dst = eth.src; eth.src = 00:00:00:00:ff:01; ip4.dst = 192.168.0.2; ip4.src = 192.168.0.1; udp.src = 67; udp.dst = 68; outport = inport; flags.loopback = 1; output;)
  table=13(ls_in_dhcp_response), priority=0    , match=(1), action=(next;)
*****

And the OVN action "put_dhcp_opts" gets translated as "controller" action and the userdata field will contain the encoded DHCP options to respond.
When ovn-controller receives the response, it just transforms the dhcp request to response by adding these already encoded options.

****
 cookie=0x2eecb540, duration=185.937s, table=20, n_packets=0, n_bytes=0, priority=100,udp,reg14=0x1,metadata=0x1,dl_src=50:54:00:00:00:01,nw_src=0.0.0.0,nw_dst=255.255.255.255,tp_src=68,tp_dst=67 actions=controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.63.c0.a8.00.02.33.04.00.00.0e.10.01.04.ff.ff.ff.00.36.04.c0.a8.00.01,pause),resubmit(,21)

***
Notice the userdata field.

In order to support this requirement, we need to parse the dhcp options in ovn-controller and only then include if they are part of the "options request list".

As per the RFC I don't think it mandates that the server can not include other options.

Here is what the man page of "dhcp-options" say - https://linux.die.net/man/5/dhcpd-options

***
option dhcp-parameter-request-list uint16;
This option, when sent by the client, specifies which options the client wishes the server to return. Normally, in the ISC DHCP client, this is done using the request statement. If this option is not specified by the client, the DHCP server will normally return every option that is valid in scope and that fits into the reply. When this option is specified on the server, the server returns the specified options. This can be used to force a client to take options that it hasn't requested, and it can also be used to tailor the response of the DHCP server for clients that may need a more limited set of options than those the server would normally return.
****

So if suppose a dhcp server is configured with "request-list", it forces the clients to use them irrespective of what the client has included in its request packet.

If I see the isc_dhcp code here - https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=blob;f=server/dhcp.c;h=5af022fbcb18225e8d4e9034d569c929bd2ad484;hb=HEAD#l3545
It first checks for the request list configured with server and then looks for the client requested list.

The point I am trying to make is that, It would be wrong for the client to assume that the dhcp options requested by it in the "request-list" will be honored by the dhcp server.
DHCP server can override them if it is configured with the request-list.


Regarding addressing it in ovn-controller - my personal opinion is that - CMS should rather use dhcp agent if it wants full fledged dhcp server behavior.
As being the author of adding dhcp responder support in OVN, I can say that, it was intended only for simple usecases - https://github.com/openvswitch/ovs/commit/281977f72ede2f03b778896c58b1f1013ca6aee6


Numan

Comment 8 Brian Haley 2019-03-18 19:14:17 UTC
I read the RFC(s) too, and it wasn't clear to me how the server should respond in this case.

But looking at the dnsmasq code it does seem to only send most options if asked by the client.

Comment 9 Gris Ge 2019-03-21 02:29:06 UTC
(In reply to Brian Haley from comment #8)
> I read the RFC(s) too, and it wasn't clear to me how the server should
> respond in this case.
> 

The rfc2131 has:

    The server MUST supply as many of the requested parameters as
                           ^^^^^^^
    possible and MUST omit any parameters it cannot provide.


The `as many ... as possible` is the key here. I am not an English native speaker, 
but I guess that means identical.

> But looking at the dnsmasq code it does seem to only send most options if
> asked by the client.

I tested on dnsmasq-2.76-7.el7.x86_64, it still option `classless-static-route(33)`
even not requested.

I guess the blame is the DHCP server, but the dhclient /usr/sbin/dhclient-script
could use some help to ignore options not in request list.

Comment 10 Numan Siddique 2019-03-27 12:20:00 UTC
I will close this bug as "Won't fix".

Feel free to reopen it if it is required.


Note You need to log in before you can comment on or make changes to this bug.