From 195c8086244e33ec42fd9fc8354eaedfd849bbba Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 15 Mar 2011 09:46:39 -0700 Subject: [PATCH] ofproto: Remove controller discovery support. I've never heard of anyone actually using controller discovery. It adds a great deal of code to the source tree, and a little bit of complication to ofproto, so this commit removes it. --- INSTALL.OpenFlow | 20 +- debian/openvswitch-controller.README.Debian | 8 +- debian/openvswitch-switch.install | 1 - debian/openvswitch-switch.manpages | 1 - lib/automake.mk | 5 +- lib/dhcp-client.c | 1105 ------------------- lib/dhcp-client.h | 57 - lib/dhcp.c | 824 -------------- lib/dhcp.h | 220 +--- lib/netdev-provider.h | 14 +- lib/rconn.c | 44 - lib/rconn.h | 3 +- ofproto/automake.mk | 2 - ofproto/discovery.c | 243 ---- ofproto/discovery.h | 38 - ofproto/ofproto.c | 90 +- ofproto/ofproto.h | 6 +- tests/.gitignore | 1 - tests/automake.mk | 6 - tests/test-dhcp-client.c | 184 --- utilities/.gitignore | 2 - utilities/automake.mk | 7 - utilities/ovs-appctl.8.in | 3 +- utilities/ovs-discover.8.in | 118 -- utilities/ovs-discover.c | 403 ------- utilities/ovs-openflowd.8.in | 122 +- utilities/ovs-openflowd.c | 45 +- vswitchd/bridge.c | 9 - vswitchd/vswitch.ovsschema | 8 +- vswitchd/vswitch.xml | 48 +- xenserver/openvswitch-xen.spec | 2 - 31 files changed, 40 insertions(+), 3599 deletions(-) delete mode 100644 lib/dhcp-client.c delete mode 100644 lib/dhcp-client.h delete mode 100644 lib/dhcp.c delete mode 100644 ofproto/discovery.c delete mode 100644 ofproto/discovery.h delete mode 100644 tests/test-dhcp-client.c delete mode 100644 utilities/ovs-discover.8.in delete mode 100644 utilities/ovs-discover.c diff --git a/INSTALL.OpenFlow b/INSTALL.OpenFlow index 684d01f3..10220f1f 100644 --- a/INSTALL.OpenFlow +++ b/INSTALL.OpenFlow @@ -118,10 +118,6 @@ OpenFlow switch. contact the DHCP server until the secure channel has started. The address will be obtained in step 7. - - If you are using in-band control with controller discovery, no - configuration is required at this point. You may proceed to - the next step. - 6. Run ovs-openflowd to start the secure channel connecting the datapath to a remote controller. If the controller is running on host 192.168.1.2 port 6633 (the default port), the ovs-openflowd invocation @@ -129,9 +125,6 @@ OpenFlow switch. # ovs-openflowd dp0 tcp:192.168.1.2 - - If you are using in-band control with controller discovery, omit - the second argument to the ovs-openflowd command. - - If you are using out-of-band control, add --out-of-band to the command line. @@ -139,16 +132,13 @@ OpenFlow switch. in an insecure manner. Please see INSTALL.SSL for a description of how to connect securely using SSL. -7. If you are using in-band control with manual configuration, and the - switch obtains its IP address dynamically, then you may now obtain - the switch's IP address, e.g. by invoking a DHCP client. The - secure channel will only be able to connect to the controller after - an IP address has been obtained. +7. If you are using in-band control, and the switch obtains its IP address + dynamically, then you may now obtain the switch's IP address, e.g. by + invoking a DHCP client. The secure channel will only be able to connect + to the controller after an IP address has been obtained. 8. The secure channel should connect to the controller within a few - seconds. It may take a little longer if controller discovery is in - use, because the switch must then also obtain its own IP address - and the controller's location via DHCP. + seconds. References ---------- diff --git a/debian/openvswitch-controller.README.Debian b/debian/openvswitch-controller.README.Debian index 94b95c4a..0c5fcba6 100644 --- a/debian/openvswitch-controller.README.Debian +++ b/debian/openvswitch-controller.README.Debian @@ -4,10 +4,4 @@ README.Debian for openvswitch-controller * To (re)configure the controller, edit /etc/default/openvswitch-controller and run "/etc/init.d/openvswitch-controller restart". -* To enable OpenFlow switches to automatically discover the location - of the controller, you must install and configure a DHCP server. - The ovs-openflowd(8) manpage (found in the openvswitch-switch - package) gives a working example configuration file for the ISC DHCP - server. - - -- Ben Pfaff , Wed, 8 Jul 2009 09:39:53 -0700 + -- Ben Pfaff , Fri, 4 Mar 2011 14:28:53 -0800 diff --git a/debian/openvswitch-switch.install b/debian/openvswitch-switch.install index 829d5c63..088b8606 100644 --- a/debian/openvswitch-switch.install +++ b/debian/openvswitch-switch.install @@ -1,5 +1,4 @@ _debian/ovsdb/ovsdb-server usr/bin -_debian/utilities/ovs-discover usr/sbin _debian/utilities/ovs-dpctl usr/sbin _debian/utilities/ovs-vsctl usr/sbin _debian/utilities/ovs-pcap usr/bin diff --git a/debian/openvswitch-switch.manpages b/debian/openvswitch-switch.manpages index 399cdda2..a310c7de 100644 --- a/debian/openvswitch-switch.manpages +++ b/debian/openvswitch-switch.manpages @@ -1,5 +1,4 @@ _debian/ovsdb/ovsdb-server.1 -_debian/utilities/ovs-discover.8 _debian/utilities/ovs-dpctl.8 _debian/utilities/ovs-pcap.1 _debian/utilities/ovs-tcpundump.1 diff --git a/lib/automake.mk b/lib/automake.mk index 5da1971e..f727b242 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -30,12 +30,9 @@ lib_libopenvswitch_a_SOURCES = \ lib/csum.h \ lib/daemon.c \ lib/daemon.h \ + lib/dhcp.h \ lib/dummy.c \ lib/dummy.h \ - lib/dhcp-client.c \ - lib/dhcp-client.h \ - lib/dhcp.c \ - lib/dhcp.h \ lib/dhparams.h \ lib/dirs.h \ lib/dpif-netdev.c \ diff --git a/lib/dhcp-client.c b/lib/dhcp-client.c deleted file mode 100644 index a0999bf4..00000000 --- a/lib/dhcp-client.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "dhcp-client.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "csum.h" -#include "dhcp.h" -#include "dynamic-string.h" -#include "flow.h" -#include "netdev.h" -#include "ofpbuf.h" -#include "poll-loop.h" -#include "sat-math.h" -#include "timeval.h" -#include "vlog.h" - -VLOG_DEFINE_THIS_MODULE(dhcp_client); - -#define DHCLIENT_STATES \ - DHCLIENT_STATE(INIT, 1 << 0) \ - DHCLIENT_STATE(INIT_REBOOT, 1 << 1) \ - DHCLIENT_STATE(REBOOTING, 1 << 2) \ - DHCLIENT_STATE(SELECTING, 1 << 3) \ - DHCLIENT_STATE(REQUESTING, 1 << 4) \ - DHCLIENT_STATE(BOUND, 1 << 5) \ - DHCLIENT_STATE(RENEWING, 1 << 6) \ - DHCLIENT_STATE(REBINDING, 1 << 7) \ - DHCLIENT_STATE(RELEASED, 1 << 8) -enum dhclient_state { -#define DHCLIENT_STATE(NAME, VALUE) S_##NAME = VALUE, - DHCLIENT_STATES -#undef DHCLIENT_STATE -}; - -static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60); - -static const char * -state_name(enum dhclient_state state) -{ - switch (state) { -#define DHCLIENT_STATE(NAME, VALUE) case S_##NAME: return #NAME; - DHCLIENT_STATES -#undef DHCLIENT_STATE - } - return "***ERROR***"; -} - -struct dhclient { - /* Configuration. */ - struct netdev *netdev; - - void (*modify_request)(struct dhcp_msg *, void *aux); - bool (*validate_offer)(const struct dhcp_msg *, void *aux); - void *aux; - - /* DHCP state. */ - enum dhclient_state state; - unsigned int state_entered; /* When we transitioned to this state. */ - uint32_t xid; /* In host byte order. */ - uint32_t ipaddr, netmask, router; - uint32_t server_ip; - struct dhcp_msg *binding; - bool changed; - - unsigned int retransmit, delay; /* Used by send_reliably(). */ - unsigned int max_timeout; - - unsigned int init_delay; /* Used by S_INIT. */ - - time_t lease_expiration; - unsigned int bound_timeout; - unsigned int renewing_timeout; - unsigned int rebinding_timeout; - - /* Used by dhclient_run() and dhclient_wait() */ - unsigned int min_timeout; - int received; - - /* Set when we send out a DHCPDISCOVER message. */ - uint32_t secs; - - struct ds s; -}; - -/* Minimum acceptable lease time, in seconds. */ -#define MIN_ACCEPTABLE_LEASE 15 - -static void state_transition(struct dhclient *, enum dhclient_state); -static unsigned int elapsed_in_this_state(const struct dhclient *cli); -static bool timeout(struct dhclient *, unsigned int secs); - -static void dhclient_msg_init(struct dhclient *, enum dhcp_msg_type, - struct dhcp_msg *); -static void send_reliably(struct dhclient *cli, - void (*make_packet)(struct dhclient *, - struct dhcp_msg *)); -static bool do_receive_msg(struct dhclient *, struct dhcp_msg *); -static void do_send_msg(struct dhclient *, const struct dhcp_msg *); -static bool receive_ack(struct dhclient *); - -static unsigned int fuzz(unsigned int x, int max_fuzz); -static unsigned int calc_t2(unsigned int lease); -static unsigned int calc_t1(unsigned int lease, unsigned int t2); - -static unsigned int clamp(unsigned int x, unsigned int min, unsigned int max); - -/* Creates a new DHCP client to configure the network device 'netdev_name' - * (e.g. "eth0"). - * - * If 'modify_request' is non-null, then each DHCP message to discover or - * request an address will be passed to it (along with auxiliary data 'aux'). - * It may then add any desired options to the message for transmission. - * - * If 'validate_offer' is non-null, then each DHCP message that offers an - * address will be passed to it (along with auxiliary data 'aux') for - * validation: if it returns true, the address will accepted; otherwise, it - * will be rejected. - * - * The DHCP client will not start advertising for an IP address until - * dhclient_init() is called. - * - * If successful, returns 0 and sets '*cli' to the new DHCP client. Otherwise, - * returns a positive errno value and sets '*cli' to a null pointer. */ -int -dhclient_create(const char *netdev_name, - void (*modify_request)(struct dhcp_msg *, void *aux), - bool (*validate_offer)(const struct dhcp_msg *, void *aux), - void *aux, struct dhclient **cli_) -{ - struct dhclient *cli; - struct netdev_options netdev_options; - struct netdev *netdev; - int error; - - *cli_ = NULL; - - memset(&netdev_options, 0, sizeof netdev_options); - netdev_options.name = netdev_name; - netdev_options.ethertype = ETH_TYPE_IP; - - error = netdev_open(&netdev_options, &netdev); - /* XXX install socket filter to catch only DHCP packets. */ - if (error) { - VLOG_ERR("%s: could not open network device: %s", - netdev_name, strerror(error)); - return error; - } - - error = netdev_turn_flags_on(netdev, NETDEV_UP, false); - if (error) { - VLOG_ERR("%s: could not bring device up: %s", - netdev_name, strerror(error)); - netdev_close(netdev); - return error; - } - - cli = xzalloc(sizeof *cli); - cli->modify_request = modify_request; - cli->validate_offer = validate_offer; - cli->aux = aux; - cli->netdev = netdev; - cli->state = S_RELEASED; - cli->state_entered = time_now(); - cli->xid = random_uint32(); - cli->ipaddr = 0; - cli->server_ip = 0; - cli->retransmit = cli->delay = 0; - cli->max_timeout = 64; - cli->min_timeout = 1; - ds_init(&cli->s); - cli->changed = true; - *cli_ = cli; - return 0; -} - -/* Sets the maximum amount of timeout that 'cli' will wait for a reply from - * the DHCP server before retransmitting, in seconds, to 'max_timeout'. The - * default is 64 seconds. */ -void -dhclient_set_max_timeout(struct dhclient *cli, unsigned int max_timeout) -{ - cli->max_timeout = MAX(2, max_timeout); -} - -/* Destroys 'cli' and frees all related resources. */ -void -dhclient_destroy(struct dhclient *cli) -{ - if (cli) { - dhcp_msg_uninit(cli->binding); - free(cli->binding); - netdev_close(cli->netdev); - ds_destroy(&cli->s); - free(cli); - } -} - -/* Returns the network device in use by 'cli'. The caller must not destroy - * the returned device. */ -struct netdev * -dhclient_get_netdev(struct dhclient *cli) -{ - return cli->netdev; -} - -/* Returns the name of the network device in use by 'cli'. The caller must - * not modify or destroy the returned string. */ -const char * -dhclient_get_name(const struct dhclient *cli) -{ - return netdev_get_name(cli->netdev); -} - -/* Forces 'cli' into a (re)initialization state, in which no address is bound - * but the client is advertising to obtain one. If 'requested_ip' is nonzero, - * then the client will attempt to re-bind to that IP address; otherwise, it - * will not ask for any particular address. */ -void -dhclient_init(struct dhclient *cli, uint32_t requested_ip) -{ - state_transition(cli, requested_ip ? S_INIT_REBOOT : S_INIT); - cli->ipaddr = requested_ip; - cli->min_timeout = 0; - cli->init_delay = 0; -} - -/* Forces 'cli' to release its bound IP address (if any). The client will not - * advertise for a new address until dhclient_init() is called again. */ -void -dhclient_release(struct dhclient *cli) -{ - if (dhclient_is_bound(cli)) { - struct dhcp_msg msg; - dhclient_msg_init(cli, DHCPRELEASE, &msg); - msg.ciaddr = cli->ipaddr; - do_send_msg(cli, &msg); - dhcp_msg_uninit(&msg); - } - state_transition(cli, S_RELEASED); - cli->min_timeout = UINT_MAX; -} - -static void -do_force_renew(struct dhclient *cli, int deadline) -{ - time_t now = time_now(); - unsigned int lease_left = sat_sub(cli->lease_expiration, now); - if (lease_left <= deadline) { - if (cli->state & (S_RENEWING | S_REBINDING)) { - return; - } - deadline = lease_left; - } - if (cli->state & (S_BOUND | S_RENEWING)) { - state_transition(cli, S_RENEWING); - cli->renewing_timeout = deadline * 3 / 4; - cli->rebinding_timeout = deadline * 1 / 4; - } else { - state_transition(cli, S_REBINDING); - cli->rebinding_timeout = deadline; - } - cli->min_timeout = 0; -} - -/* Forces 'cli' to attempt to renew the lease its current IP address (if any) - * within 'deadline' seconds. If the deadline is not met, then the client - * gives up its IP address binding and re-starts the DHCP process. */ -void -dhclient_force_renew(struct dhclient *cli, int deadline) -{ - /* Drain the receive queue so that we know that any DHCPACK we process is - * freshly received. */ - netdev_drain(cli->netdev); - - switch (cli->state) { - case S_INIT: - case S_INIT_REBOOT: - case S_REBOOTING: - case S_SELECTING: - case S_REQUESTING: - break; - - case S_BOUND: - case S_RENEWING: - case S_REBINDING: - do_force_renew(cli, deadline); - break; - - case S_RELEASED: - dhclient_init(cli, 0); - break; - } -} - -/* Returns true if 'cli' is bound to an IP address, false otherwise. */ -bool -dhclient_is_bound(const struct dhclient *cli) -{ - return cli->state & (S_BOUND | S_RENEWING | S_REBINDING); -} - -/* Returns true if 'cli' has changed from bound to unbound, or vice versa, at - * least once since the last time this function was called. */ -bool -dhclient_changed(struct dhclient *cli) -{ - bool changed = cli->changed; - cli->changed = 0; - return changed; -} - -/* Returns 'cli''s current state, as a string. The caller must not modify or - * free the string. */ -const char * -dhclient_get_state(const struct dhclient *cli) -{ - return state_name(cli->state); -} - -/* Returns the number of seconds spent so far in 'cli''s current state. */ -unsigned int -dhclient_get_state_elapsed(const struct dhclient *cli) -{ - return elapsed_in_this_state(cli); -} - -/* If 'cli' is bound, returns the number of seconds remaining in its lease; - * otherwise, returns 0. */ -unsigned int -dhclient_get_lease_remaining(const struct dhclient *cli) -{ - if (dhclient_is_bound(cli)) { - time_t now = time_now(); - return cli->lease_expiration > now ? cli->lease_expiration - now : 0; - } else { - return 0; - } -} - -/* If 'cli' is bound to an IP address, returns that IP address; otherwise, - * returns 0. */ -uint32_t -dhclient_get_ip(const struct dhclient *cli) -{ - return dhclient_is_bound(cli) ? cli->ipaddr : 0; -} - -/* If 'cli' is bound to an IP address, returns the netmask for that IP address; - * otherwise, returns 0. */ -uint32_t -dhclient_get_netmask(const struct dhclient *cli) -{ - return dhclient_is_bound(cli) ? cli->netmask : 0; -} - -/* If 'cli' is bound to an IP address and 'cli' has a default gateway, returns - * that default gateway; otherwise, returns 0. */ -uint32_t -dhclient_get_router(const struct dhclient *cli) -{ - return dhclient_is_bound(cli) ? cli->router : 0; -} - -/* If 'cli' is bound to an IP address, returns the DHCP message that was - * received to obtain that IP address (so that the caller can obtain additional - * options from it). Otherwise, returns a null pointer. */ -const struct dhcp_msg * -dhclient_get_config(const struct dhclient *cli) -{ - return dhclient_is_bound(cli) ? cli->binding : NULL; -} - -/* Configures the network device backing 'cli' to the network address and other - * parameters obtained via DHCP. If no address is bound on 'cli', removes any - * configured address from 'cli'. - * - * To use a dhclient as a regular DHCP client that binds and unbinds from IP - * addresses in the usual fashion, call this function after dhclient_run() if - * anything has changed, like so: - * - * dhclient_run(cli); - * if (dhclient_changed(cli)) { - * dhclient_configure_netdev(cli); - * } - * - */ -int -dhclient_configure_netdev(struct dhclient *cli) -{ - const char *cli_name = dhclient_get_name(cli); - struct in_addr addr = { dhclient_get_ip(cli) }; - struct in_addr mask = { dhclient_get_netmask(cli) }; - struct in_addr router = { dhclient_get_router(cli) }; - int error; - - error = netdev_set_in4(cli->netdev, addr, mask); - if (error) { - VLOG_ERR("%s: could not set address "IP_FMT"/"IP_FMT" (%s)", - cli_name, IP_ARGS(&addr.s_addr), IP_ARGS(&mask.s_addr), - strerror(error)); - } - - if (!error && router.s_addr) { - error = netdev_add_router(cli->netdev, router); - if (error) { - VLOG_ERR("%s: failed to add default route to "IP_FMT" (%s)", - cli_name, IP_ARGS(&router), strerror(error)); - } - } - - return error; -} - -/* If 'cli' is bound and the binding includes DNS domain parameters, updates - * /etc/resolv.conf will be updated to match the received parameters. Returns - * 0 if successful, otherwise a positive errno value. */ -int -dhclient_update_resolv_conf(struct dhclient *cli) -{ - const char *cli_name = dhclient_get_name(cli); - uint32_t dns_server; - char *domain_name; - bool has_domain_name; - char new_name[128]; - FILE *old, *new; - int i; - - if (!dhclient_is_bound(cli)) { - return 0; - } - if (!dhcp_msg_get_ip(cli->binding, DHCP_CODE_DNS_SERVER, 0, &dns_server)) { - VLOG_DBG("%s: binding does not include any DNS servers", cli_name); - return 0; - } - - sprintf(new_name, "/etc/resolv.conf.tmp%ld", (long int) getpid()); - new = fopen(new_name, "w"); - if (!new) { - VLOG_WARN("%s: could not create %s (%s)", - cli_name, new_name, strerror(errno)); - return errno; - } - - domain_name = dhcp_msg_get_string(cli->binding, DHCP_CODE_DOMAIN_NAME); - has_domain_name = domain_name != NULL; - if (domain_name) { - if (strspn(domain_name, "-_.0123456789abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(domain_name)) { - fprintf(new, "domain %s\n", domain_name); - } else { - VLOG_WARN("%s: ignoring invalid domain name %s", - cli_name, domain_name); - has_domain_name = false; - } - } else { - VLOG_DBG("%s: binding does not include domain name", cli_name); - } - free(domain_name); - - for (i = 0; dhcp_msg_get_ip(cli->binding, DHCP_CODE_DNS_SERVER, - i, &dns_server); i++) { - fprintf(new, "nameserver "IP_FMT"\n", IP_ARGS(&dns_server)); - } - - old = fopen("/etc/resolv.conf", "r"); - if (old) { - char line[128]; - - while (fgets(line, sizeof line, old)) { - char *kw = xmemdup0(line, strcspn(line, " \t\r\n")); - if (strcmp(kw, "nameserver") - && (!has_domain_name - || (strcmp(kw, "domain") && strcmp(kw, "search")))) { - fputs(line, new); - } - free(kw); - } - fclose(old); - } else { - VLOG_DBG("%s: failed to open /etc/resolv.conf (%s)", - cli_name, strerror(errno)); - } - - if (fclose(new) < 0) { - VLOG_WARN("%s: closing %s failed (%s)", - cli_name, new_name, strerror(errno)); - return errno; - } - - if (rename(new_name, "/etc/resolv.conf") < 0) { - VLOG_WARN("%s: failed to rename %s to /etc/resolv.conf (%s)", - cli_name, new_name, strerror(errno)); - return errno; - } - - return 0; -} - -/* DHCP protocol. */ - -static void -make_dhcpdiscover(struct dhclient *cli, struct dhcp_msg *msg) -{ - cli->secs = elapsed_in_this_state(cli); - dhclient_msg_init(cli, DHCPDISCOVER, msg); - if (cli->ipaddr) { - dhcp_msg_put_ip(msg, DHCP_CODE_REQUESTED_IP, cli->ipaddr); - } -} - -static void -make_dhcprequest(struct dhclient *cli, struct dhcp_msg *msg) -{ - dhclient_msg_init(cli, DHCPREQUEST, msg); - msg->ciaddr = dhclient_get_ip(cli); - if (cli->state == S_REQUESTING) { - dhcp_msg_put_ip(msg, DHCP_CODE_SERVER_IDENTIFIER, cli->server_ip); - } - dhcp_msg_put_ip(msg, DHCP_CODE_REQUESTED_IP, cli->ipaddr); -} - -static void -do_init(struct dhclient *cli, enum dhclient_state next_state) -{ - if (!cli->init_delay) { - cli->init_delay = fuzz(2, 1); - } - if (timeout(cli, cli->init_delay)) { - state_transition(cli, next_state); - } -} - -static void -dhclient_run_INIT(struct dhclient *cli) -{ - do_init(cli, S_SELECTING); -} - -static void -dhclient_run_INIT_REBOOT(struct dhclient *cli) -{ - do_init(cli, S_REBOOTING); -} - -static void -dhclient_run_REBOOTING(struct dhclient *cli) -{ - send_reliably(cli, make_dhcprequest); - if (!receive_ack(cli) && timeout(cli, 60)) { - state_transition(cli, S_INIT); - } -} - -static bool -dhcp_receive(struct dhclient *cli, unsigned int msgs, struct dhcp_msg *msg) -{ - while (do_receive_msg(cli, msg)) { - const char *cli_name = dhclient_get_name(cli); - - if (msg->type > 31 || !((1u << msg->type) & msgs)) { - VLOG_DBG_RL(&rl, "%s: received unexpected %s in %s state: %s", - cli_name, - dhcp_type_name(msg->type), state_name(cli->state), - dhcp_msg_to_string(msg, false, &cli->s)); - } else if (msg->xid != cli->xid) { - VLOG_DBG_RL(&rl, "%s: ignoring %s with xid != %08"PRIx32" " - "in %s state: %s", cli_name, - dhcp_type_name(msg->type), msg->xid, - state_name(cli->state), - dhcp_msg_to_string(msg, false, &cli->s)); - } else { - return true; - } - dhcp_msg_uninit(msg); - } - return false; -} - -static bool -validate_offered_options(struct dhclient *cli, const struct dhcp_msg *msg) -{ - const char *cli_name = dhclient_get_name(cli); - uint32_t lease, netmask; - - if (!dhcp_msg_get_secs(msg, DHCP_CODE_LEASE_TIME, 0, &lease)) { - VLOG_WARN_RL(&rl, "%s: %s lacks lease time (%s)", - cli_name, dhcp_type_name(msg->type), - dhcp_msg_to_string(msg, false, &cli->s)); - } else if (!dhcp_msg_get_ip(msg, DHCP_CODE_SUBNET_MASK, 0, &netmask)) { - VLOG_WARN_RL(&rl, "%s: %s lacks netmask (%s)", - cli_name, dhcp_type_name(msg->type), - dhcp_msg_to_string(msg, false, &cli->s)); - } else if (lease < MIN_ACCEPTABLE_LEASE) { - VLOG_WARN_RL(&rl, "%s: ignoring %s with %"PRIu32"-second " - "lease time (%s)", cli_name, - dhcp_type_name(msg->type), lease, - dhcp_msg_to_string(msg, false, &cli->s)); - } else if (cli->validate_offer && !cli->validate_offer(msg, cli->aux)) { - VLOG_DBG_RL(&rl, "%s: client validation hook refused offer (%s)", - cli_name, dhcp_msg_to_string(msg, false, &cli->s)); - } else { - return true; - } - return false; -} - -static void -dhclient_run_SELECTING(struct dhclient *cli) -{ - const char *cli_name = dhclient_get_name(cli); - struct dhcp_msg msg; - - send_reliably(cli, make_dhcpdiscover); - if (cli->server_ip && timeout(cli, 60)) { - cli->server_ip = 0; - state_transition(cli, S_INIT); - } - for (; dhcp_receive(cli, 1u << DHCPOFFER, &msg); dhcp_msg_uninit(&msg)) { - if (!validate_offered_options(cli, &msg)) { - continue; - } - if (!dhcp_msg_get_ip(&msg, DHCP_CODE_SERVER_IDENTIFIER, - 0, &cli->server_ip)) { - VLOG_WARN_RL(&rl, "%s: DHCPOFFER lacks server identifier (%s)", - cli_name, dhcp_msg_to_string(&msg, false, &cli->s)); - continue; - } - - VLOG_DBG_RL(&rl, "%s: accepting DHCPOFFER (%s)", - cli_name, dhcp_msg_to_string(&msg, false, &cli->s)); - cli->ipaddr = msg.yiaddr; - state_transition(cli, S_REQUESTING); - break; - } -} - -static bool -same_binding(const char *cli_name, - const struct dhcp_msg *old, const struct dhcp_msg *new) -{ - static const int codes[] = { - DHCP_CODE_SUBNET_MASK, - DHCP_CODE_ROUTER, - DHCP_CODE_DNS_SERVER, - DHCP_CODE_HOST_NAME, - DHCP_CODE_DOMAIN_NAME, - DHCP_CODE_IP_TTL, - DHCP_CODE_MTU, - DHCP_CODE_BROADCAST_ADDRESS, - DHCP_CODE_STATIC_ROUTE, - DHCP_CODE_ARP_CACHE_TIMEOUT, - DHCP_CODE_ETHERNET_ENCAPSULATION, - DHCP_CODE_TCP_TTL, - DHCP_CODE_SERVER_IDENTIFIER, - DHCP_CODE_OFP_CONTROLLER_VCONN, - DHCP_CODE_OFP_PKI_URI, - }; - int i; - bool same = true; - - if (old->yiaddr != new->yiaddr) { - VLOG_WARN("%s: DHCP binding changed IP address " - "from "IP_FMT" to "IP_FMT, - cli_name, IP_ARGS(&old->yiaddr), IP_ARGS(&new->yiaddr)); - same = false; - } - for (i = 0; i < ARRAY_SIZE(codes); i++) { - int code = codes[i]; - const struct dhcp_option *old_opt = &old->options[code]; - const struct dhcp_option *new_opt = &new->options[code]; - if (!dhcp_option_equals(old_opt, new_opt)) { - struct ds old_string = DS_EMPTY_INITIALIZER; - struct ds new_string = DS_EMPTY_INITIALIZER; - VLOG_WARN("%s: DHCP binding changed option from %s to %s", - cli_name, - dhcp_option_to_string(old_opt, code, &old_string), - dhcp_option_to_string(new_opt, code, &new_string)); - ds_destroy(&old_string); - ds_destroy(&new_string); - same = false; - } - } - return same; -} - -static bool -receive_ack(struct dhclient *cli) -{ - struct dhcp_msg msg; - - if (!dhcp_receive(cli, (1u << DHCPACK) | (1u << DHCPNAK), &msg)) { - return false; - } else if (msg.type == DHCPNAK) { - dhcp_msg_uninit(&msg); - state_transition(cli, S_INIT); - return true; - } else if (!validate_offered_options(cli, &msg)) { - dhcp_msg_uninit(&msg); - return false; - } else { - uint32_t lease = 0, t1 = 0, t2 = 0; - - if (cli->binding) { - if (!same_binding(dhclient_get_name(cli), cli->binding, &msg)) { - cli->changed = true; - } - dhcp_msg_uninit(cli->binding); - } else { - cli->binding = xmalloc(sizeof *cli->binding); - } - dhcp_msg_copy(cli->binding, &msg); - - dhcp_msg_get_secs(&msg, DHCP_CODE_LEASE_TIME, 0, &lease); - dhcp_msg_get_secs(&msg, DHCP_CODE_T1, 0, &t1); - dhcp_msg_get_secs(&msg, DHCP_CODE_T2, 0, &t2); - assert(lease >= MIN_ACCEPTABLE_LEASE); - - if (!t2 || t2 >= lease) { - t2 = calc_t2(lease); - } - if (!t1 || t1 >= t2) { - t1 = calc_t1(lease, t2); - } - - cli->lease_expiration = sat_add(time_now(), lease); - cli->bound_timeout = t1; - cli->renewing_timeout = t2 - t1; - cli->rebinding_timeout = lease - t2; - - cli->ipaddr = msg.yiaddr; - dhcp_msg_get_ip(&msg, DHCP_CODE_SUBNET_MASK, 0, &cli->netmask); - if (!dhcp_msg_get_ip(&msg, DHCP_CODE_ROUTER, 0, &cli->router)) { - cli->router = INADDR_ANY; - } - state_transition(cli, S_BOUND); - VLOG_DBG("%s: bound (%s)", dhclient_get_name(cli), - dhcp_msg_to_string(&msg, false, &cli->s)); - return true; - } -} - -static void -dhclient_run_REQUESTING(struct dhclient *cli) -{ - send_reliably(cli, make_dhcprequest); - if (!receive_ack(cli) && timeout(cli, 60)) { - state_transition(cli, S_INIT); - } -} - -static void -dhclient_run_BOUND(struct dhclient *cli) -{ - if (timeout(cli, cli->bound_timeout)) { - state_transition(cli, S_RENEWING); - } -} - -static void -dhclient_run_RENEWING(struct dhclient *cli) -{ - send_reliably(cli, make_dhcprequest); - if (!receive_ack(cli) && timeout(cli, cli->renewing_timeout)) { - state_transition(cli, S_REBINDING); - } -} - -static void -dhclient_run_REBINDING(struct dhclient *cli) -{ - send_reliably(cli, make_dhcprequest); - if (!receive_ack(cli) && timeout(cli, cli->rebinding_timeout)) { - state_transition(cli, S_INIT); - } -} - -static void -dhclient_run_RELEASED(struct dhclient *cli OVS_UNUSED) -{ - /* Nothing to do. */ -} - -/* Processes the DHCP protocol for 'cli'. */ -void -dhclient_run(struct dhclient *cli) -{ - int old_state; - do { - old_state = cli->state; - cli->min_timeout = UINT_MAX; - cli->received = 0; - switch (cli->state) { -#define DHCLIENT_STATE(NAME, VALUE) \ - case S_##NAME: dhclient_run_##NAME(cli); break; - DHCLIENT_STATES -#undef DHCLIENT_STATE - default: - NOT_REACHED(); - } - } while (cli->state != old_state); -} - -/* Sets up poll timeouts to wake up the poll loop when 'cli' needs to do some - * work. */ -void -dhclient_wait(struct dhclient *cli) -{ - if (cli->min_timeout != UINT_MAX) { - long long int wake = sat_add(cli->state_entered, cli->min_timeout); - poll_timer_wait_until(wake * 1000); - } - /* Reset timeout to 1 second. This will have no effect ordinarily, because - * dhclient_run() will typically set it back to a higher value. If, - * however, the caller fails to call dhclient_run() before its next call to - * dhclient_wait() we won't potentially block forever. */ - cli->min_timeout = 1; - - if (cli->state & (S_SELECTING | S_REQUESTING | S_RENEWING | S_REBINDING)) { - netdev_recv_wait(cli->netdev); - } -} - -static void -state_transition(struct dhclient *cli, enum dhclient_state state) -{ - const char *cli_name = dhclient_get_name(cli); - bool was_bound = dhclient_is_bound(cli); - bool am_bound; - - if (cli->state != state) { - VLOG_DBG("%s: entering %s", cli_name, state_name(state)); - cli->state = state; - } - cli->state_entered = time_now(); - cli->retransmit = cli->delay = 0; - am_bound = dhclient_is_bound(cli); - if (was_bound != am_bound) { - cli->changed = true; - if (am_bound) { - assert(cli->binding != NULL); - VLOG_INFO("%s: obtained address "IP_FMT", netmask "IP_FMT, - cli_name, - IP_ARGS(&cli->ipaddr), IP_ARGS(&cli->netmask)); - if (cli->router) { - VLOG_INFO("%s: obtained default gateway "IP_FMT, - cli_name, IP_ARGS(&cli->router)); - } - } else { - dhcp_msg_uninit(cli->binding); - free(cli->binding); - cli->binding = NULL; - - VLOG_INFO("%s: network address unbound", cli_name); - } - } - if (cli->state & (S_SELECTING | S_REQUESTING | S_REBOOTING)) { - netdev_drain(cli->netdev); - } -} - -static void -send_reliably(struct dhclient *cli, - void (*make_packet)(struct dhclient *, struct dhcp_msg *)) -{ - if (timeout(cli, cli->retransmit)) { - struct dhcp_msg msg; - make_packet(cli, &msg); - if (cli->modify_request) { - cli->modify_request(&msg, cli->aux); - } - do_send_msg(cli, &msg); - cli->delay = MIN(cli->max_timeout, MAX(4, cli->delay * 2)); - cli->retransmit += fuzz(cli->delay, 1); - dhcp_msg_uninit(&msg); - } -} - -static void -dhclient_msg_init(struct dhclient *cli, enum dhcp_msg_type type, - struct dhcp_msg *msg) -{ - dhcp_msg_init(msg); - msg->op = DHCP_BOOTREQUEST; - msg->xid = cli->xid; - msg->secs = cli->secs; - msg->type = type; - netdev_get_etheraddr(cli->netdev, msg->chaddr); -} - -/* If time goes backward this returns a large number, which makes it look like - * we've been in the current state a very long time. That's probably - * fine for that corner case--we'll just expire our lease, etc., and try to - * get a new one. */ -static unsigned int -elapsed_in_this_state(const struct dhclient *cli) -{ - return time_now() - cli->state_entered; -} - -static bool -timeout(struct dhclient *cli, unsigned int secs) -{ - cli->min_timeout = MIN(cli->min_timeout, secs); - return time_now() >= sat_add(cli->state_entered, secs); -} - -static bool -do_receive_msg(struct dhclient *cli, struct dhcp_msg *msg) -{ - const char *cli_name = dhclient_get_name(cli); - uint8_t cli_mac[ETH_ADDR_LEN]; - struct ofpbuf b; - - ofpbuf_init(&b, ETH_TOTAL_MAX + VLAN_ETH_HEADER_LEN); - netdev_get_etheraddr(cli->netdev, cli_mac); - for (; cli->received < 50; cli->received++) { - const struct ip_header *ip; - const struct dhcp_header *dhcp; - struct flow flow; - int error; - - ofpbuf_clear(&b); - error = netdev_recv(cli->netdev, &b); - if (error) { - goto drained; - } - - flow_extract(&b, 0, 0, &flow); - if (flow.dl_type != htons(ETH_TYPE_IP) - || flow.nw_proto != IPPROTO_UDP - || flow.tp_dst != htons(DHCP_CLIENT_PORT) - || !(eth_addr_is_broadcast(flow.dl_dst) - || eth_addr_equals(flow.dl_dst, cli_mac))) { - continue; - } - - ip = b.l3; - if (IP_IS_FRAGMENT(ip->ip_frag_off)) { - /* We don't do reassembly. */ - VLOG_WARN_RL(&rl, "%s: ignoring fragmented DHCP datagram", - cli_name); - continue; - } - - dhcp = b.l7; - if (!dhcp) { - VLOG_WARN_RL(&rl, "%s: ignoring DHCP datagram with missing " - "payload", cli_name); - continue; - } - - ofpbuf_pull(&b, (char *)b.l7 - (char*)b.data); - error = dhcp_parse(msg, &b); - if (!error) { - if (VLOG_IS_DBG_ENABLED()) { - VLOG_DBG_RL(&rl, "%s: received %s", cli_name, - dhcp_msg_to_string(msg, false, &cli->s)); - } else { - VLOG_INFO_RL(&rl, "%s: received %s", - cli_name, dhcp_type_name(msg->type)); - } - ofpbuf_uninit(&b); - return true; - } - } - netdev_drain(cli->netdev); -drained: - ofpbuf_uninit(&b); - return false; -} - -static void -do_send_msg(struct dhclient *cli, const struct dhcp_msg *msg) -{ - const char *cli_name = dhclient_get_name(cli); - struct ofpbuf b; - struct eth_header eh; - struct ip_header nh; - struct udp_header th; - uint32_t udp_csum; - int error; - - ofpbuf_init(&b, ETH_TOTAL_MAX); - ofpbuf_reserve(&b, ETH_HEADER_LEN + IP_HEADER_LEN + UDP_HEADER_LEN); - - dhcp_assemble(msg, &b); - - netdev_get_etheraddr(cli->netdev, eh.eth_src); - memcpy(eh.eth_dst, eth_addr_broadcast, ETH_ADDR_LEN); - eh.eth_type = htons(ETH_TYPE_IP); - - nh.ip_ihl_ver = IP_IHL_VER(5, IP_VERSION); - nh.ip_tos = 0; - nh.ip_tot_len = htons(IP_HEADER_LEN + UDP_HEADER_LEN + b.size); - /* We can't guarantee uniqueness of ip_id versus the host's, screwing up - * fragment reassembly, so prevent fragmentation and use an all-zeros - * ip_id. RFC 791 doesn't say we can do this, but Linux does the same - * thing for DF packets, so it must not screw anything up. */ - nh.ip_id = 0; - nh.ip_frag_off = htons(IP_DONT_FRAGMENT); - nh.ip_ttl = 64; - nh.ip_proto = IPPROTO_UDP; - nh.ip_csum = 0; - nh.ip_src = dhclient_get_ip(cli); - /* XXX need to use UDP socket for nonzero server IPs so that we can get - * routing table support. - * - * if (...have server IP and in appropriate state...) { - * nh.ip_dst = cli->server_ip; - * } else { - * nh.ip_dst = INADDR_BROADCAST; - * } - */ - nh.ip_dst = INADDR_BROADCAST; - nh.ip_csum = csum(&nh, sizeof nh); - - th.udp_src = htons(DHCP_CLIENT_PORT); - th.udp_dst = htons(DHCP_SERVER_PORT); - th.udp_len = htons(UDP_HEADER_LEN + b.size); - th.udp_csum = 0; - udp_csum = csum_add32(0, nh.ip_src); - udp_csum = csum_add32(udp_csum, nh.ip_dst); - udp_csum = csum_add16(udp_csum, IPPROTO_UDP << 8); - udp_csum = csum_add16(udp_csum, th.udp_len); - udp_csum = csum_continue(udp_csum, &th, sizeof th); - th.udp_csum = csum_finish(csum_continue(udp_csum, b.data, b.size)); - - ofpbuf_push(&b, &th, sizeof th); - ofpbuf_push(&b, &nh, sizeof nh); - ofpbuf_push(&b, &eh, sizeof eh); - - /* Don't try to send the frame if it's too long for an Ethernet frame. We - * disregard the network device's actual MTU because we don't want the - * frame to have to be discarded or fragmented if it travels over a regular - * Ethernet at some point. 1500 bytes should be enough for anyone. */ - if (b.size <= ETH_TOTAL_MAX) { - if (VLOG_IS_DBG_ENABLED()) { - VLOG_DBG("%s: sending %s", - cli_name, dhcp_msg_to_string(msg, false, &cli->s)); - } else { - VLOG_INFO("%s: sending %s", cli_name, dhcp_type_name(msg->type)); - } - error = netdev_send(cli->netdev, &b); - if (error) { - VLOG_ERR("%s: send failed on %s (%s)", cli_name, - netdev_get_name(cli->netdev), strerror(error)); - } - } else { - VLOG_ERR("%s: cannot send %zu-byte Ethernet frame", cli_name, b.size); - } - - ofpbuf_uninit(&b); -} - -static unsigned int -fuzz(unsigned int x, int max_fuzz) -{ - /* Generate number in range [-max_fuzz, +max_fuzz]. */ - int fuzz = random_range(max_fuzz * 2 + 1) - max_fuzz; - unsigned int y = x + fuzz; - return fuzz >= 0 ? (y >= x ? y : UINT_MAX) : (y <= x ? y : 0); -} - -static unsigned int -clamp(unsigned int x, unsigned int min, unsigned int max) -{ - return x < min ? min : x > max ? max : x; -} - -static unsigned int -calc_t2(unsigned int lease) -{ - unsigned int base = lease * 0.875; - return lease >= 60 ? clamp(fuzz(base, 10), 0, lease - 1) : base; -} - -static unsigned int -calc_t1(unsigned int lease, unsigned int t2) -{ - unsigned int base = lease / 2; - return lease >= 60 ? clamp(fuzz(base, 10), 0, t2 - 1) : base; -} diff --git a/lib/dhcp-client.h b/lib/dhcp-client.h deleted file mode 100644 index b4c3065c..00000000 --- a/lib/dhcp-client.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2008, 2010 Nicira Networks. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DHCP_CLIENT_H -#define DHCP_CLIENT_H 1 - -#include -#include - -struct dhclient; -struct dhcp_msg; -struct netdev; -int dhclient_create(const char *netdev, - void (*modify_request)(struct dhcp_msg *, void *aux), - bool (*validate_offer)(const struct dhcp_msg *, void *aux), - void *aux, struct dhclient **); -void dhclient_set_max_timeout(struct dhclient *, unsigned int max_timeout); -void dhclient_destroy(struct dhclient *); - -struct netdev *dhclient_get_netdev(struct dhclient *); -const char *dhclient_get_name(const struct dhclient *); - -void dhclient_init(struct dhclient *, uint32_t requested_ip); -void dhclient_release(struct dhclient *); -void dhclient_force_renew(struct dhclient *, int deadline); -bool dhclient_is_bound(const struct dhclient *); -bool dhclient_changed(struct dhclient *); - -const char *dhclient_get_state(const struct dhclient *); -unsigned int dhclient_get_state_elapsed(const struct dhclient *); -unsigned int dhclient_get_lease_remaining(const struct dhclient *); - -uint32_t dhclient_get_ip(const struct dhclient *); -uint32_t dhclient_get_netmask(const struct dhclient *); -uint32_t dhclient_get_router(const struct dhclient *); -const struct dhcp_msg *dhclient_get_config(const struct dhclient *); - -int dhclient_configure_netdev(struct dhclient *); -int dhclient_update_resolv_conf(struct dhclient *); - -void dhclient_run(struct dhclient *); -void dhclient_wait(struct dhclient *); - -#endif /* dhcp-client.h */ diff --git a/lib/dhcp.c b/lib/dhcp.c deleted file mode 100644 index 62ede06e..00000000 --- a/lib/dhcp.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (c) 2008, 2010 Nicira Networks. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "dhcp.h" -#include -#include -#include -#include -#include -#include -#include "dynamic-string.h" -#include "ofpbuf.h" -#include "vlog.h" - -VLOG_DEFINE_THIS_MODULE(dhcp); - -/* Information about a DHCP argument type. */ -struct arg_type { - const char *name; /* Name. */ - size_t size; /* Number of bytes per argument. */ -}; - -static struct arg_type types[] = { -#define DHCP_ARG(NAME, SIZE) [DHCP_ARG_##NAME] = {#NAME, SIZE}, - DHCP_ARGS -#undef DHCP_ARG -}; - -/* Information about a DHCP option. */ -struct option_class { - const char *name; /* Name. */ - enum dhcp_arg_type type; /* Argument type. */ - size_t min_args; /* Minimum number of arguments. */ - size_t max_args; /* Maximum number of arguments. */ -}; - -static const struct option_class * -get_option_class(int code) -{ - static struct option_class classes[DHCP_N_OPTIONS]; - static bool init = false; - if (!init) { - int i; - - init = true; -#define DHCP_OPT(NAME, CODE, TYPE, MIN, MAX) \ - classes[CODE].name = #NAME; \ - classes[CODE].type = DHCP_ARG_##TYPE; \ - classes[CODE].min_args = MIN; \ - classes[CODE].max_args = MAX; - DHCP_OPTS -#undef DHCP_OPT - - for (i = 0; i < DHCP_N_OPTIONS; i++) { - if (!classes[i].name) { - classes[i].name = xasprintf("option-%d", i); - classes[i].type = DHCP_ARG_UINT8; - classes[i].min_args = 0; - classes[i].max_args = SIZE_MAX; - } - } - } - assert(code >= 0 && code < DHCP_N_OPTIONS); - return &classes[code]; -} - -/* A single (bad) DHCP message can in theory dump out many, many log messages, - * especially at high logging levels, so the burst size is set quite high - * here to avoid missing useful information. */ -struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 600); - -static void copy_data(struct dhcp_msg *); - -const char * -dhcp_type_name(enum dhcp_msg_type type) -{ - switch (type) { -#define DHCP_MSG(NAME, VALUE) case NAME: return #NAME; - DHCP_MSGS -#undef DHCP_MSG - } - return "<>"; -} - -/* Initializes 'msg' as a DHCP message. The message should be freed with - * dhcp_msg_uninit() when it is no longer needed. */ -void -dhcp_msg_init(struct dhcp_msg *msg) -{ - memset(msg, 0, sizeof *msg); -} - -/* Frees the contents of 'msg'. The caller is responsible for freeing 'msg', - * if necessary. */ -void -dhcp_msg_uninit(struct dhcp_msg *msg) -{ - if (msg) { - free(msg->data); - } -} - -/* Initializes 'dst' as a copy of 'src'. 'dst' (and 'src') should be freed - * with dhcp_msg_uninit() when it is no longer needed. */ -void -dhcp_msg_copy(struct dhcp_msg *dst, const struct dhcp_msg *src) -{ - *dst = *src; - dst->data_allocated = src->data_used; - dst->data_used = 0; - dst->data = xmalloc(dst->data_allocated); - copy_data(dst); -} - -static void -prealloc_data(struct dhcp_msg *msg, size_t n) -{ - size_t needed = msg->data_used + n; - if (needed > msg->data_allocated) { - uint8_t *old_data = msg->data; - msg->data_allocated = MAX(needed * 2, 64); - msg->data = xmalloc(msg->data_allocated); - if (old_data) { - copy_data(msg); - free(old_data); - } - } -} - -static void * -append_data(struct dhcp_msg *msg, const void *data, size_t n) -{ - uint8_t *p = &msg->data[msg->data_used]; - memcpy(p, data, n); - msg->data_used += n; - return p; -} - -static void -copy_data(struct dhcp_msg *msg) -{ - int code; - - msg->data_used = 0; - for (code = 0; code < DHCP_N_OPTIONS; code++) { - struct dhcp_option *opt = &msg->options[code]; - if (opt->data) { - assert(msg->data_used + opt->n <= msg->data_allocated); - opt->data = append_data(msg, opt->data, opt->n); - } - } -} - -/* Appends the 'n' bytes in 'data' to the DHCP option in 'msg' represented by - * 'code' (which must be in the range 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put(struct dhcp_msg *msg, int code, - const void *data, size_t n) -{ - struct dhcp_option *opt; - if (code == DHCP_CODE_PAD || code == DHCP_CODE_END) { - return; - } - - opt = &msg->options[code]; - prealloc_data(msg, n + opt->n); - if (opt->n) { - if (&msg->data[msg->data_used - opt->n] != opt->data) { - opt->data = append_data(msg, opt->data, opt->n); - } - append_data(msg, data, n); - } else { - opt->data = append_data(msg, data, n); - } - opt->n += n; -} - -/* Appends the boolean value 'b', as a octet with value 0 (false) or 1 (true), - * to the DHCP option in 'msg' represented by 'code' (which must be in the - * range 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put_bool(struct dhcp_msg *msg, int code, bool b_) -{ - char b = !!b_; - dhcp_msg_put(msg, code, &b, 1); -} - -/* Appends the number of seconds 'secs', as a 32-bit number in network byte - * order, to the DHCP option in 'msg' represented by 'code' (which must be in - * the range 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put_secs(struct dhcp_msg *msg, int code, uint32_t secs_) -{ - uint32_t secs = htonl(secs_); - dhcp_msg_put(msg, code, &secs, sizeof secs); -} - -/* Appends the IP address 'ip', as a 32-bit number in network byte order, to - * the DHCP option in 'msg' represented by 'code' (which must be in the range - * 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put_ip(struct dhcp_msg *msg, int code, uint32_t ip) -{ - dhcp_msg_put(msg, code, &ip, sizeof ip); -} - -/* Appends the ASCII string 'string', to the DHCP option in 'msg' represented - * by 'code' (which must be in the range 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put_string(struct dhcp_msg *msg, int code, const char *string) -{ - dhcp_msg_put(msg, code, string, strlen(string)); -} - -/* Appends octet 'x' to DHCP option in 'msg' represented by 'code' (which must - * be in the range 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put_uint8(struct dhcp_msg *msg, int code, uint8_t x) -{ - dhcp_msg_put(msg, code, &x, sizeof x); -} - -/* Appends the 'n' octets in 'data' to DHCP option in 'msg' represented by - * 'code' (which must be in the range 0...DHCP_N_OPTIONS). */ -void dhcp_msg_put_uint8_array(struct dhcp_msg *msg, int code, - const uint8_t data[], size_t n) -{ - dhcp_msg_put(msg, code, data, n); -} - -/* Appends the 16-bit value in 'x', in network byte order, to DHCP option in - * 'msg' represented by 'code' (which must be in the range - * 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put_uint16(struct dhcp_msg *msg, int code, uint16_t x_) -{ - uint16_t x = htons(x_); - dhcp_msg_put(msg, code, &x, sizeof x); -} - - -/* Appends the 'n' 16-bit values in 'data', in network byte order, to DHCP - * option in 'msg' represented by 'code' (which must be in the range - * 0...DHCP_N_OPTIONS). */ -void -dhcp_msg_put_uint16_array(struct dhcp_msg *msg, int code, - const uint16_t data[], size_t n) -{ - size_t i; - - for (i = 0; i < n; i++) { - dhcp_msg_put_uint16(msg, code, data[i]); - } -} - -/* Returns a pointer to the 'size' bytes starting at byte offset 'offset' in - * the DHCP option in 'msg' represented by 'code' (which must be in the range - * 0...DHCP_N_OPTIONS). If the option has fewer than 'offset + size' bytes, - * returns a null pointer. */ -const void * -dhcp_msg_get(const struct dhcp_msg *msg, int code, - size_t offset, size_t size) -{ - const struct dhcp_option *opt = &msg->options[code]; - return offset + size <= opt->n ? (const char *) opt->data + offset : NULL; -} - -/* Stores in '*out' the boolean value at byte offset 'offset' in the DHCP - * option in 'msg' represented by 'code' (which must be in the range - * 0...DHCP_N_OPTIONS). Returns true if successful, false if the option has - * fewer than 'offset + 1' bytes. */ -bool -dhcp_msg_get_bool(const struct dhcp_msg *msg, int code, size_t offset, - bool *out) -{ - const uint8_t *uint8 = dhcp_msg_get(msg, code, offset, sizeof *uint8); - if (uint8) { - *out = *uint8 != 0; - return true; - } else { - return false; - } -} - -/* Stores in '*out' the 32-bit count of seconds at offset 'offset' (in - * 4-byte increments) in the DHCP option in 'msg' represented by 'code' - * (which must be in the range 0...DHCP_N_OPTIONS). The value is converted to - * native byte order. Returns true if successful, false if the option has - * fewer than '4 * (offset + 1)' bytes. */ -bool -dhcp_msg_get_secs(const struct dhcp_msg *msg, int code, size_t offset, - uint32_t *out) -{ - const uint32_t *uint32 = dhcp_msg_get(msg, code, offset * sizeof *uint32, - sizeof *uint32); - if (uint32) { - *out = ntohl(*uint32); - return true; - } else { - return false; - } -} - -/* Stores in '*out' the IP address at offset 'offset' (in 4-byte increments) in - * the DHCP option in 'msg' represented by 'code' (which must be in the range - * 0...DHCP_N_OPTIONS). The IP address is stored in network byte order. - * Returns true if successful, false if the option has fewer than '4 * (offset - * + 1)' bytes. */ -bool -dhcp_msg_get_ip(const struct dhcp_msg *msg, int code, - size_t offset, uint32_t *out) -{ - const uint32_t *uint32 = dhcp_msg_get(msg, code, offset * sizeof *uint32, - sizeof *uint32); - if (uint32) { - *out = *uint32; - return true; - } else { - return false; - } -} - -/* Returns the string in the DHCP option in 'msg' represented by 'code' (which - * must be in the range 0...DHCP_N_OPTIONS). The caller is responsible for - * freeing the string with free(). - * - * If 'msg' has no option represented by 'code', returns a null pointer. (If - * the option was specified but had no content, then an empty string is - * returned, not a null pointer.) */ -char * -dhcp_msg_get_string(const struct dhcp_msg *msg, int code) -{ - const struct dhcp_option *opt = &msg->options[code]; - return opt->data ? xmemdup0(opt->data, opt->n) : NULL; -} - -/* Stores in '*out' the octet at byte offset 'offset' in the DHCP option in - * 'msg' represented by 'code' (which must be in the range 0...DHCP_N_OPTIONS). - * Returns true if successful, false if the option has fewer than 'offset + 1' - * bytes. */ -bool -dhcp_msg_get_uint8(const struct dhcp_msg *msg, int code, - size_t offset, uint8_t *out) -{ - const uint8_t *uint8 = dhcp_msg_get(msg, code, offset, sizeof *uint8); - if (uint8) { - *out = *uint8; - return true; - } else { - return false; - } -} - -/* Stores in '*out' the 16-bit value at offset 'offset' (in 2-byte units) in - * the DHCP option in 'msg' represented by 'code' (which must be in the range - * 0...DHCP_N_OPTIONS). The value is converted to native byte order. Returns - * true if successful, false if the option has fewer than '2 * (offset + 1)' - * bytes. */ -bool -dhcp_msg_get_uint16(const struct dhcp_msg *msg, int code, - size_t offset, uint16_t *out) -{ - const uint16_t *uint16 = dhcp_msg_get(msg, code, offset * sizeof *uint16, - sizeof *uint16); - if (uint16) { - *out = ntohs(*uint16); - return true; - } else { - return false; - } -} - -/* Appends a string representing 'duration' seconds to 'ds'. */ -static void -put_duration(struct ds *ds, unsigned int duration) -{ - if (duration) { - if (duration >= 86400) { - ds_put_format(ds, "%ud", duration / 86400); - duration %= 86400; - } - if (duration >= 3600) { - ds_put_format(ds, "%uh", duration / 3600); - duration %= 3600; - } - if (duration >= 60) { - ds_put_format(ds, "%umin", duration / 60); - duration %= 60; - } - if (duration > 0) { - ds_put_format(ds, "%us", duration); - } - } else { - ds_put_cstr(ds, "0s"); - } -} - -/* Appends a string representation of 'opt', which has the given 'code', to - * 'ds'. */ -const char * -dhcp_option_to_string(const struct dhcp_option *opt, int code, struct ds *ds) -{ - const struct option_class *class = get_option_class(code); - const struct arg_type *type = &types[class->type]; - size_t offset; - const char *cp; - - for (cp = class->name; *cp; cp++) { - unsigned char c = *cp; - ds_put_char(ds, c == '_' ? '-' : tolower(c)); - } - ds_put_char(ds, '='); - - if (!opt->data || !opt->n) { - ds_put_cstr(ds, opt->data ? "empty" : "null"); - return ds_cstr(ds); - } - - if (class->type == DHCP_ARG_STRING) { - ds_put_char(ds, '"'); - ds_put_printable(ds, opt->data, opt->n); - ds_put_char(ds, '"'); - return ds_cstr(ds); - } - for (offset = 0; offset + type->size <= opt->n; offset += type->size) { - const void *p = (const char *) opt->data + offset; - const uint8_t *uint8 = p; - const uint32_t *uint32 = p; - const uint16_t *uint16 = p; - - if (offset && class->type != DHCP_ARG_STRING) { - ds_put_cstr(ds, class->type == DHCP_ARG_UINT8 ? ":" : ", "); - } - switch (class->type) { - case DHCP_ARG_FIXED: - NOT_REACHED(); - case DHCP_ARG_IP: - ds_put_format(ds, IP_FMT, IP_ARGS(uint32)); - break; - case DHCP_ARG_UINT8: - ds_put_format(ds, "%02"PRIx8, *uint8); - break; - case DHCP_ARG_UINT16: - ds_put_format(ds, "%"PRIu16, ntohs(*uint16)); - break; - case DHCP_ARG_UINT32: - ds_put_format(ds, "%"PRIu32, ntohl(*uint32)); - break; - case DHCP_ARG_SECS: - put_duration(ds, ntohl(*uint32)); - break; - case DHCP_ARG_STRING: - NOT_REACHED(); - case DHCP_ARG_BOOLEAN: - if (*uint8 == 0) { - ds_put_cstr(ds, "false"); - } else if (*uint8 == 1) { - ds_put_cstr(ds, "true"); - } else { - ds_put_format(ds, "**%"PRIu8"**", *uint8); - } - break; - } - } - if (offset != opt->n) { - if (offset) { - ds_put_cstr(ds, ", "); - } - ds_put_cstr(ds, "**leftovers:"); - for (; offset < opt->n; offset++) { - const void *p = (const char *) opt->data + offset; - const uint8_t *uint8 = p; - ds_put_format(ds, " %"PRIu8, *uint8); - } - ds_put_cstr(ds, "**"); - } - return ds_cstr(ds); -} - -/* Returns true if 'a' and 'b' have the same content, false otherwise. */ -bool -dhcp_option_equals(const struct dhcp_option *a, const struct dhcp_option *b) -{ - return ((a->data != NULL) == (b->data != NULL) - && a->n == b->n - && (!a->data || !memcmp(a->data, b->data, a->n))); -} - -/* Replaces 'ds' by a string representation of 'msg'. If 'multiline' is - * false, 'ds' receives a single-line representation of 'msg', otherwise a - * multiline representation. */ -const char * -dhcp_msg_to_string(const struct dhcp_msg *msg, bool multiline, struct ds *ds) -{ - char separator = multiline ? '\n' : ' '; - int code; - - ds_clear(ds); - ds_put_format(ds, "op=%s", - (msg->op == DHCP_BOOTREQUEST ? "request" - : msg->op == DHCP_BOOTREPLY ? "reply" - : "error")); - ds_put_format(ds, "%ctype=%s", separator, dhcp_type_name(msg->type)); - ds_put_format(ds, "%cxid=0x%08"PRIx32, separator, msg->xid); - ds_put_format(ds, "%csecs=", separator); - put_duration(ds, msg->secs); - if (msg->flags) { - ds_put_format(ds, "%cflags=", separator); - if (msg->flags & DHCP_FLAGS_BROADCAST) { - ds_put_cstr(ds, "[BROADCAST]"); - } - if (msg->flags & DHCP_FLAGS_MBZ) { - ds_put_format(ds, "[0x%04"PRIx16"]", msg->flags & DHCP_FLAGS_MBZ); - } - } - if (msg->ciaddr) { - ds_put_format(ds, "%cciaddr="IP_FMT, separator, IP_ARGS(&msg->ciaddr)); - } - if (msg->yiaddr) { - ds_put_format(ds, "%cyiaddr="IP_FMT, separator, IP_ARGS(&msg->yiaddr)); - } - if (msg->siaddr) { - ds_put_format(ds, "%csiaddr="IP_FMT, separator, IP_ARGS(&msg->siaddr)); - } - if (msg->giaddr) { - ds_put_format(ds, "%cgiaddr="IP_FMT, separator, IP_ARGS(&msg->giaddr)); - } - ds_put_format(ds, "%cchaddr="ETH_ADDR_FMT, - separator, ETH_ADDR_ARGS(msg->chaddr)); - - for (code = 0; code < DHCP_N_OPTIONS; code++) { - const struct dhcp_option *opt = &msg->options[code]; - if (opt->data) { - ds_put_char(ds, separator); - dhcp_option_to_string(opt, code, ds); - } - } - if (multiline) { - ds_put_char(ds, separator); - } - return ds_cstr(ds); -} - -static void -parse_options(struct dhcp_msg *msg, const char *name, void *data, size_t size, - int option_offset) -{ - struct ofpbuf b; - - ofpbuf_use_const(&b, data, size); - for (;;) { - uint8_t *code, *len; - void *payload; - - code = ofpbuf_try_pull(&b, 1); - if (!code || *code == DHCP_CODE_END) { - break; - } else if (*code == DHCP_CODE_PAD) { - continue; - } - - len = ofpbuf_try_pull(&b, 1); - if (!len) { - VLOG_DBG_RL(&rl, "reached end of %s expecting length byte", name); - break; - } - - payload = ofpbuf_try_pull(&b, *len); - if (!payload) { - VLOG_DBG_RL(&rl, "expected %"PRIu8" bytes of option-%"PRIu8" " - "payload with only %zu bytes of %s left", - *len, *code, b.size, name); - break; - } - dhcp_msg_put(msg, *code + option_offset, payload, *len); - } -} - -static void -validate_options(struct dhcp_msg *msg) -{ - int code; - - for (code = 0; code < DHCP_N_OPTIONS; code++) { - struct dhcp_option *opt = &msg->options[code]; - const struct option_class *class = get_option_class(code); - struct arg_type *type = &types[class->type]; - if (opt->data) { - size_t n_elems = opt->n / type->size; - size_t remainder = opt->n % type->size; - bool ok = true; - if (remainder) { - VLOG_DBG_RL(&rl, "%s option has %zu %zu-byte %s arguments " - "with %zu bytes left over", - class->name, n_elems, type->size, - type->name, remainder); - ok = false; - } - if (n_elems < class->min_args || n_elems > class->max_args) { - VLOG_DBG_RL(&rl, "%s option has %zu %zu-byte %s arguments but " - "between %zu and %zu are required", - class->name, n_elems, type->size, type->name, - class->min_args, class->max_args); - ok = false; - } - if (!ok) { - struct ds ds = DS_EMPTY_INITIALIZER; - VLOG_DBG_RL(&rl, "%s option contains: %s", class->name, - dhcp_option_to_string(opt, code, &ds)); - ds_destroy(&ds); - - opt->n = 0; - opt->data = NULL; - } - } - } -} - -/* Attempts to parse 'b' as a DHCP message. If successful, initializes '*msg' - * to the parsed message and returns 0. Otherwise, returns a positive errno - * value and '*msg' is indeterminate. */ -int -dhcp_parse(struct dhcp_msg *msg, const struct ofpbuf *b_) -{ - struct ofpbuf b = *b_; - struct dhcp_header *dhcp; - uint32_t *cookie; - uint8_t type; - char *vendor_class; - - dhcp = ofpbuf_try_pull(&b, sizeof *dhcp); - if (!dhcp) { - VLOG_DBG_RL(&rl, "buffer too small for DHCP header (%zu bytes)", - b.size); - goto error; - } - - if (dhcp->op != DHCP_BOOTREPLY && dhcp->op != DHCP_BOOTREQUEST) { - VLOG_DBG_RL(&rl, "invalid DHCP op (%"PRIu8")", dhcp->op); - goto error; - } - if (dhcp->htype != ARP_HRD_ETHERNET) { - VLOG_DBG_RL(&rl, "invalid DHCP htype (%"PRIu8")", dhcp->htype); - goto error; - } - if (dhcp->hlen != ETH_ADDR_LEN) { - VLOG_DBG_RL(&rl, "invalid DHCP hlen (%"PRIu8")", dhcp->hlen); - goto error; - } - - dhcp_msg_init(msg); - msg->op = dhcp->op; - msg->xid = ntohl(dhcp->xid); - msg->secs = ntohs(dhcp->secs); - msg->flags = ntohs(dhcp->flags); - msg->ciaddr = dhcp->ciaddr; - msg->yiaddr = dhcp->yiaddr; - msg->siaddr = dhcp->siaddr; - msg->giaddr = dhcp->giaddr; - memcpy(msg->chaddr, dhcp->chaddr, ETH_ADDR_LEN); - - cookie = ofpbuf_try_pull(&b, sizeof *cookie); - if (cookie) { - if (ntohl(*cookie) == DHCP_OPTS_COOKIE) { - uint8_t overload; - - parse_options(msg, "options", b.data, b.size, 0); - if (dhcp_msg_get_uint8(msg, DHCP_CODE_OPTION_OVERLOAD, - 0, &overload)) { - if (overload & 1) { - parse_options(msg, "file", dhcp->file, sizeof dhcp->file, - 0); - } - if (overload & 2) { - parse_options(msg, "sname", - dhcp->sname, sizeof dhcp->sname, 0); - } - } - } else { - VLOG_DBG_RL(&rl, "bad DHCP options cookie: %08"PRIx32, - ntohl(*cookie)); - } - } else { - VLOG_DBG_RL(&rl, "DHCP packet has no options"); - } - - vendor_class = dhcp_msg_get_string(msg, DHCP_CODE_VENDOR_CLASS); - if (vendor_class && !strcmp(vendor_class, "OpenFlow")) { - parse_options(msg, "vendor-specific", - msg->options[DHCP_CODE_VENDOR_SPECIFIC].data, - msg->options[DHCP_CODE_VENDOR_SPECIFIC].n, - DHCP_VENDOR_OFS); - } - free(vendor_class); - - validate_options(msg); - if (!dhcp_msg_get_uint8(msg, DHCP_CODE_DHCP_MSG_TYPE, 0, &type)) { - VLOG_DBG_RL(&rl, "missing DHCP message type"); - dhcp_msg_uninit(msg); - goto error; - } - msg->type = type; - return 0; - -error: - if (VLOG_IS_DBG_ENABLED()) { - struct ds ds; - - ds_init(&ds); - ds_put_hex_dump(&ds, b_->data, b_->size, 0, true); - VLOG_DBG_RL(&rl, "invalid DHCP message dump:\n%s", ds_cstr(&ds)); - - ds_clear(&ds); - dhcp_msg_to_string(msg, false, &ds); - VLOG_DBG_RL(&rl, "partially dissected DHCP message: %s", ds_cstr(&ds)); - - ds_destroy(&ds); - } - return EPROTO; -} - -static void -put_option_chunk(struct ofpbuf *b, uint8_t code, void *data, size_t n) -{ - uint8_t header[2]; - - assert(n < 256); - header[0] = code; - header[1] = n; - ofpbuf_put(b, header, sizeof header); - ofpbuf_put(b, data, n); -} - -static void -put_option(struct ofpbuf *b, uint8_t code, void *data, size_t n) -{ - if (data) { - if (n) { - /* Divide the data into chunks of 255 bytes or less. Make - * intermediate chunks multiples of 8 bytes in case the - * recipient validates a chunk at a time instead of the - * concatenated value. */ - uint8_t *p = data; - while (n) { - size_t chunk = n > 255 ? 248 : n; - put_option_chunk(b, code, p, chunk); - p += chunk; - n -= chunk; - } - } else { - /* Option should be present but carry no data. */ - put_option_chunk(b, code, NULL, 0); - } - } -} - -/* Appends to 'b' the DHCP message represented by 'msg'. */ -void -dhcp_assemble(const struct dhcp_msg *msg, struct ofpbuf *b) -{ - const uint8_t end = DHCP_CODE_END; - uint32_t cookie = htonl(DHCP_OPTS_COOKIE); - struct ofpbuf vnd_data; - struct dhcp_header dhcp; - int i; - - memset(&dhcp, 0, sizeof dhcp); - dhcp.op = msg->op; - dhcp.htype = ARP_HRD_ETHERNET; - dhcp.hlen = ETH_ADDR_LEN; - dhcp.hops = 0; - dhcp.xid = htonl(msg->xid); - dhcp.secs = htons(msg->secs); - dhcp.flags = htons(msg->flags); - dhcp.ciaddr = msg->ciaddr; - dhcp.yiaddr = msg->yiaddr; - dhcp.siaddr = msg->siaddr; - dhcp.giaddr = msg->giaddr; - memcpy(dhcp.chaddr, msg->chaddr, ETH_ADDR_LEN); - ofpbuf_put(b, &dhcp, sizeof dhcp); - ofpbuf_put(b, &cookie, sizeof cookie); - - /* Put DHCP message type first. (The ordering is not required but it - * seems polite.) */ - if (msg->type) { - uint8_t type = msg->type; - put_option(b, DHCP_CODE_DHCP_MSG_TYPE, &type, 1); - } - - /* Put the standard options. */ - for (i = 0; i < DHCP_VENDOR_OFS; i++) { - const struct dhcp_option *option = &msg->options[i]; - put_option(b, i, option->data, option->n); - } - - /* Assemble vendor specific option and put it. */ - ofpbuf_init(&vnd_data, 0); - for (i = DHCP_VENDOR_OFS; i < DHCP_N_OPTIONS; i++) { - const struct dhcp_option *option = &msg->options[i]; - put_option(&vnd_data, i - DHCP_VENDOR_OFS, option->data, option->n); - } - if (vnd_data.size) { - put_option(b, DHCP_CODE_VENDOR_SPECIFIC, vnd_data.data, vnd_data.size); - } - ofpbuf_uninit(&vnd_data); - - /* Put end-of-options option. */ - ofpbuf_put(b, &end, sizeof end); -} - diff --git a/lib/dhcp.h b/lib/dhcp.h index 96696a24..b3682263 100644 --- a/lib/dhcp.h +++ b/lib/dhcp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Nicira Networks. + * Copyright (c) 2008, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,24 +21,10 @@ #include "packets.h" #include "util.h" -struct ds; -struct ofpbuf; - /* Ports used by DHCP. */ #define DHCP_SERVER_PORT 67 /* Port used by DHCP server. */ #define DHCP_CLIENT_PORT 68 /* Port used by DHCP client. */ -/* Values for 'op' field. */ -#define DHCP_BOOTREQUEST 1 /* Message sent by DHCP client. */ -#define DHCP_BOOTREPLY 2 /* Message sent by DHCP server. */ - -/* Bits in 'flags' field. */ -#define DHCP_FLAGS_BROADCAST 0x8000 /* Server must broadcast all replies. */ -#define DHCP_FLAGS_MBZ 0x7fff /* Must be zero. */ - -/* First four bytes of 'options' field. */ -#define DHCP_OPTS_COOKIE 0x63825363 - #define DHCP_HEADER_LEN 236 struct dhcp_header { uint8_t op; /* DHCP_BOOTREQUEST or DHCP_BOOTREPLY. */ @@ -59,208 +45,4 @@ struct dhcp_header { }; BUILD_ASSERT_DECL(DHCP_HEADER_LEN == sizeof(struct dhcp_header)); -#define DHCP_ARGS \ - DHCP_ARG(FIXED, 0) /* Fixed-length option (PAD and END only). */ \ - DHCP_ARG(IP, 4) /* IP addresses. */ \ - DHCP_ARG(SECS, 4) /* 32-bit duration in seconds. */ \ - DHCP_ARG(STRING, 1) /* NVT string, optionally null-terminated. */ \ - DHCP_ARG(UINT8, 1) /* 8-bit unsigned integer. */ \ - DHCP_ARG(UINT16, 2) /* 16-bit unsigned integer. */ \ - DHCP_ARG(UINT32, 4) /* 32-bit unsigned integer. */ \ - DHCP_ARG(BOOLEAN, 1) /* Boolean octet (0 or 1). */ - -/* DHCP option argument types. */ -enum dhcp_arg_type { -#define DHCP_ARG(NAME, SIZE) DHCP_ARG_##NAME, - DHCP_ARGS -#undef DHCP_ARG -}; - -#define DHCP_MSGS \ - DHCP_MSG(DHCPDISCOVER, 1) /* Client->server: What IPs are available? */ \ - DHCP_MSG(DHCPOFFER, 2) /* Server->client: This IP is available. */ \ - DHCP_MSG(DHCPREQUEST, 3) /* Client->server: I want that IP. */ \ - DHCP_MSG(DHCPDECLINE, 4) /* Client->server: That IP is in use!. */ \ - DHCP_MSG(DHCPACK, 5) /* Server->client: You can have that IP. */ \ - DHCP_MSG(DHCPNAK, 6) /* Server->client: You can't have that IP. */ \ - DHCP_MSG(DHCPRELEASE, 7) /* Client->server: I'm done with this IP. */ \ - DHCP_MSG(DCHPINFORM, 8) /* Client->server: I'm using this IP. */ - -/* DHCP message type (this is the argument for the DHCP_MSG_TYPE option). */ -enum dhcp_msg_type { -#define DHCP_MSG(NAME, VALUE) NAME = VALUE, - DHCP_MSGS -#undef DHCP_MSG -}; -const char *dhcp_type_name(enum dhcp_msg_type); - -/* DHCP allows for 256 standardized options and 256 vendor-specific options. - * We put them in a single array, with the standard options at the - * beginning. */ -#define DHCP_N_OPTIONS 512 -#define DHCP_VENDOR_OFS 256 - -/* DHCP options. */ -#define DHCP_OPTS \ - /* arg min max */ \ - /* name code type args args */ \ - DHCP_OPT(PAD, 0, FIXED, 0, 0) \ - DHCP_OPT(END, 255, FIXED, 0, 0) \ - DHCP_OPT(SUBNET_MASK, 1, IP, 1, 1) \ - DHCP_OPT(TIME_OFFSET, 2, SECS, 1, 1) \ - DHCP_OPT(ROUTER, 3, IP, 1, SIZE_MAX) \ - /* Time Server Option is obsolete. */ \ - /* Name Server Option is obsolete. */ \ - DHCP_OPT(DNS_SERVER, 6, IP, 1, SIZE_MAX) \ - /* Log Server Option is obsolete. */ \ - /* Cookie Server Option is obsolete. */ \ - DHCP_OPT(LPR_SERVER, 9, IP, 1, SIZE_MAX) \ - /* Impress Server Option is obsolete. */ \ - /* Resource Location Server Option is obsolete. */ \ - DHCP_OPT(HOST_NAME, 12, STRING, 1, SIZE_MAX) \ - DHCP_OPT(BOOT_FILE_SIZE, 13, UINT16, 1, 1) \ - /* Merit Dump File option is obsolete. */ \ - DHCP_OPT(DOMAIN_NAME, 15, STRING, 1, SIZE_MAX) \ - /* Swap Server option is obsolete. */ \ - DHCP_OPT(ROOT_PATH, 17, STRING, 1, SIZE_MAX) \ - DHCP_OPT(EXTENSIONS_PATH, 18, STRING, 1, SIZE_MAX) \ - DHCP_OPT(IP_FORWARDING, 19, BOOLEAN, 1, 1) \ - DHCP_OPT(SOURCE_ROUTING, 20, BOOLEAN, 1, 1) \ - DHCP_OPT(POLICY_FILTER, 21, IP, 2, SIZE_MAX) \ - DHCP_OPT(MAX_DGRAM_REASSEMBLY, 22, UINT16, 1, 1) \ - DHCP_OPT(IP_TTL, 23, UINT8, 1, 1) \ - DHCP_OPT(PATH_MTU_TIMEOUT, 24, SECS, 1, 1) \ - DHCP_OPT(PATH_MTU_PLATEAU, 25, UINT16, 2, SIZE_MAX) \ - DHCP_OPT(MTU, 26, UINT16, 1, 1) \ - DHCP_OPT(ALL_SUBNETS_ARE_LOCAL, 27, BOOLEAN, 1, 1) \ - DHCP_OPT(BROADCAST_ADDRESS, 28, IP, 1, 1) \ - DHCP_OPT(PERFORM_MASK_DISCOVERY, 29, BOOLEAN, 1, 1) \ - DHCP_OPT(MASK_SUPPLIER, 30, BOOLEAN, 1, 1) \ - DHCP_OPT(PERFORM_ROUTER_DISCOVERY, 31, BOOLEAN, 1, 1) \ - DHCP_OPT(ROUTER_SOLICITATION, 32, IP, 1, 1) \ - DHCP_OPT(STATIC_ROUTE, 33, IP, 2, SIZE_MAX) \ - /* Trailer Encapsulation Option is obsolete. */ \ - DHCP_OPT(ARP_CACHE_TIMEOUT, 35, SECS, 1, 1) \ - DHCP_OPT(ETHERNET_ENCAPSULATION, 36, BOOLEAN, 1, 1) \ - DHCP_OPT(TCP_TTL, 37, UINT8, 1, 1) \ - DHCP_OPT(TCP_KEEPALIVE_INTERVAL, 38, SECS, 1, 1) \ - DHCP_OPT(TCP_KEEPALIVE_GARBAGE, 39, BOOLEAN, 1, 1) \ - DHCP_OPT(NIS_DOMAIN, 40, STRING, 1, SIZE_MAX) \ - DHCP_OPT(NIS_SERVERS, 41, IP, 1, SIZE_MAX) \ - DHCP_OPT(NTP_SERVERS, 42, IP, 1, SIZE_MAX) \ - DHCP_OPT(VENDOR_SPECIFIC, 43, UINT8, 1, SIZE_MAX) \ - DHCP_OPT(NETBIOS_NS, 44, IP, 1, SIZE_MAX) \ - DHCP_OPT(NETBIOS_DDS, 45, IP, 1, SIZE_MAX) \ - DHCP_OPT(NETBIOS_NODE_TYPE, 46, UINT8, 1, 1) \ - DHCP_OPT(NETBIOS_SCOPE, 47, STRING, 1, SIZE_MAX) \ - DHCP_OPT(X_FONT_SERVER, 48, IP, 1, SIZE_MAX) \ - DHCP_OPT(XDM, 49, IP, 1, SIZE_MAX) \ - DHCP_OPT(NISPLUS_DOMAIN, 64, STRING, 1, SIZE_MAX) \ - DHCP_OPT(NISPLUS_SERVERS, 65, IP, 1, SIZE_MAX) \ - DHCP_OPT(MOBILE_IP_HOME_AGENT, 68, IP, 0, SIZE_MAX) \ - DHCP_OPT(SMTP_SERVER, 69, IP, 1, SIZE_MAX) \ - DHCP_OPT(POP3_SERVER, 70, IP, 1, SIZE_MAX) \ - DHCP_OPT(NNTP_SERVER, 71, IP, 1, SIZE_MAX) \ - DHCP_OPT(WWW_SERVER, 72, IP, 1, SIZE_MAX) \ - DHCP_OPT(FINGER_SERVER, 73, IP, 1, SIZE_MAX) \ - DHCP_OPT(IRC_SERVER, 74, IP, 1, SIZE_MAX) \ - /* StreetTalk Server Option is obsolete. */ \ - /* StreetTalk Directory Assistance Server Option is obsolete. */ \ - DHCP_OPT(REQUESTED_IP, 50, IP, 1, 1) \ - DHCP_OPT(LEASE_TIME, 51, SECS, 1, 1) \ - DHCP_OPT(OPTION_OVERLOAD, 52, UINT8, 1, 1) \ - DHCP_OPT(TFTP_SERVER, 66, STRING, 1, SIZE_MAX) \ - DHCP_OPT(BOOTFILE_NAME, 67, STRING, 1, SIZE_MAX) \ - DHCP_OPT(DHCP_MSG_TYPE, 53, UINT8, 1, 1) \ - DHCP_OPT(SERVER_IDENTIFIER, 54, IP, 1, 1) \ - DHCP_OPT(PARAMETER_REQUEST_LIST, 55, UINT8, 1, SIZE_MAX) \ - DHCP_OPT(MESSAGE, 56, STRING, 1, SIZE_MAX) \ - DHCP_OPT(MAX_DHCP_MSG_SIZE, 57, UINT16, 1, 1) \ - DHCP_OPT(T1, 58, SECS, 1, 1) \ - DHCP_OPT(T2, 59, SECS, 1, 1) \ - DHCP_OPT(VENDOR_CLASS, 60, STRING, 1, SIZE_MAX) \ - DHCP_OPT(CLIENT_ID, 61, UINT8, 2, SIZE_MAX) \ - DHCP_VNDOPT(OFP_CONTROLLER_VCONN, 1, STRING, 1, SIZE_MAX) \ - DHCP_VNDOPT(OFP_PKI_URI, 2, STRING, 1, SIZE_MAX) - -/* Shorthand for defining vendor options (used above). */ -#define DHCP_VNDOPT(NAME, CODE, ARG, MIN, MAX) \ - DHCP_OPT(NAME, (CODE) + DHCP_VENDOR_OFS, ARG, MIN, MAX) - -/* DHCP option codes. */ -enum { -#define DHCP_OPT(NAME, VALUE, ARGTYPE, MIN_ARGS, MAX_ARGS) \ - DHCP_CODE_##NAME = VALUE, -DHCP_OPTS -#undef DHCP_OPT -}; - -/* The contents of a DHCP option. - * - * DHCP options can (rarely) be present but lack content. To represent such an - * option, 'n' is 0 and 'data' is non-null (but does not point to anything - * useful). */ -struct dhcp_option { - size_t n; /* Number of bytes of data. */ - void *data; /* Data. */ -}; - -const char *dhcp_option_to_string(const struct dhcp_option *, int code, - struct ds *); -bool dhcp_option_equals(const struct dhcp_option *, - const struct dhcp_option *); - -/* Abstracted DHCP protocol message, to make them easier to manipulate than - * through raw protocol buffers. */ -struct dhcp_msg { - /* For use by calling code. */ - uint8_t op; /* DHCP_BOOTREQUEST or DHCP_BOOTREPLY. */ - uint32_t xid; /* Transaction ID. */ - uint16_t secs; /* Since client started address acquisition. */ - uint16_t flags; /* DHCP_FLAGS_*. */ - uint32_t ciaddr; /* Client IP, if it has a lease for one. */ - uint32_t yiaddr; /* Client ("your") IP address. */ - uint32_t siaddr; /* Next server IP address. */ - uint32_t giaddr; /* Relay agent IP address. */ - uint8_t chaddr[ETH_ADDR_LEN]; /* Client hardware address. */ - enum dhcp_msg_type type; /* DHCP_CODE_DHCP_MSG_TYPE option argument. */ - struct dhcp_option options[DHCP_N_OPTIONS]; /* Indexed by option code. */ - - /* For direct use only by dhcp_msg_*() functions. */ - uint8_t *data; - size_t data_used, data_allocated; -}; - -void dhcp_msg_init(struct dhcp_msg *); -void dhcp_msg_uninit(struct dhcp_msg *); -void dhcp_msg_copy(struct dhcp_msg *, const struct dhcp_msg *); -void dhcp_msg_put(struct dhcp_msg *, int code, const void *, size_t); -void dhcp_msg_put_bool(struct dhcp_msg *, int code, bool); -void dhcp_msg_put_secs(struct dhcp_msg *, int code, uint32_t); -void dhcp_msg_put_ip(struct dhcp_msg *, int code, uint32_t); -void dhcp_msg_put_string(struct dhcp_msg *, int code, const char *); -void dhcp_msg_put_uint8(struct dhcp_msg *, int code, uint8_t); -void dhcp_msg_put_uint8_array(struct dhcp_msg *, int code, - const uint8_t[], size_t n); -void dhcp_msg_put_uint16(struct dhcp_msg *, int code, uint16_t); -void dhcp_msg_put_uint16_array(struct dhcp_msg *, int code, - const uint16_t[], size_t n); -const void *dhcp_msg_get(const struct dhcp_msg *, int code, size_t offset, - size_t size); -bool dhcp_msg_get_bool(const struct dhcp_msg *, int code, - size_t offset, bool *); -bool dhcp_msg_get_secs(const struct dhcp_msg *, int code, - size_t offset, uint32_t *); -bool dhcp_msg_get_ip(const struct dhcp_msg *, int code, - size_t offset, uint32_t *); -char *dhcp_msg_get_string(const struct dhcp_msg *, int code); -bool dhcp_msg_get_uint8(const struct dhcp_msg *, int code, - size_t offset, uint8_t *); -bool dhcp_msg_get_uint16(const struct dhcp_msg *, int code, - size_t offset, uint16_t *); -const char *dhcp_msg_to_string(const struct dhcp_msg *, bool multiline, - struct ds *); -int dhcp_parse(struct dhcp_msg *, const struct ofpbuf *); -void dhcp_assemble(const struct dhcp_msg *, struct ofpbuf *); - #endif /* dhcp.h */ diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index be51c48a..1a916f76 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -175,10 +175,9 @@ struct netdev_class { * * May return -EOPNOTSUPP if a network device does not implement packet * reception through this interface. This function may be set to null if - * it would always return -EOPNOTSUPP anyhow. (This will disable the OVS - * integrated DHCP client and OpenFlow controller discovery, and prevent - * the network device from being usefully used by the netdev-based - * "userspace datapath".) */ + * it would always return -EOPNOTSUPP anyhow. (This will prevent the + * network device from being usefully used by the netdev-based "userspace + * datapath".) */ int (*recv)(struct netdev *netdev, void *buffer, size_t size); /* Registers with the poll loop to wake up from the next call to @@ -209,10 +208,9 @@ struct netdev_class { * * May return EOPNOTSUPP if a network device does not implement packet * transmission through this interface. This function may be set to null - * if it would always return EOPNOTSUPP anyhow. (This will disable the OVS - * integrated DHCP client and OpenFlow controller discovery, and prevent - * the network device from being usefully used by the netdev-based - * "userspace datapath".) */ + * if it would always return EOPNOTSUPP anyhow. (This will prevent the + * network device from being usefully used by the netdev-based "userspace + * datapath".) */ int (*send)(struct netdev *netdev, const void *buffer, size_t size); /* Registers with the poll loop to wake up from the next call to diff --git a/lib/rconn.c b/lib/rconn.c index 6a86de6c..0e18ab48 100644 --- a/lib/rconn.c +++ b/lib/rconn.c @@ -104,16 +104,6 @@ struct rconn { time_t creation_time; unsigned long int total_time_connected; - /* If we can't connect to the peer, it could be for any number of reasons. - * Usually, one would assume it is because the peer is not running or - * because the network is partitioned. But it could also be because the - * network topology has changed, in which case the upper layer will need to - * reassess it (in particular, obtain a new IP address via DHCP and find - * the new location of the controller). We set this flag when we suspect - * that this could be the case. */ - bool questionable_connectivity; - time_t last_questioned; - /* Throughout this file, "probe" is shorthand for "inactivity probe". * When nothing has been received from the peer for a while, we send out * an echo request as an inactivity probe packet. We should receive back @@ -149,7 +139,6 @@ static void reconnect(struct rconn *); static void report_error(struct rconn *, int error); static void disconnect(struct rconn *, int error); static void flush_queue(struct rconn *); -static void question_connectivity(struct rconn *); static void copy_to_monitor(struct rconn *, const struct ofpbuf *); static bool is_connected_state(enum state); static bool is_admitted_msg(const struct ofpbuf *); @@ -204,9 +193,6 @@ rconn_create(int probe_interval, int max_backoff) rc->creation_time = time_now(); rc->total_time_connected = 0; - rc->questionable_connectivity = false; - rc->last_questioned = time_now(); - rconn_set_probe_interval(rc, probe_interval); rc->n_monitors = 0; @@ -464,7 +450,6 @@ static void run_IDLE(struct rconn *rc) { if (timed_out(rc)) { - question_connectivity(rc); VLOG_ERR("%s: no response to inactivity probe after %u " "seconds, disconnecting", rc->name, elapsed_in_this_state(rc)); @@ -746,22 +731,6 @@ rconn_get_local_port(const struct rconn *rconn) return rconn->vconn ? vconn_get_local_port(rconn->vconn) : 0; } -/* If 'rconn' can't connect to the peer, it could be for any number of reasons. - * Usually, one would assume it is because the peer is not running or because - * the network is partitioned. But it could also be because the network - * topology has changed, in which case the upper layer will need to reassess it - * (in particular, obtain a new IP address via DHCP and find the new location - * of the controller). When this appears that this might be the case, this - * function returns true. It also clears the questionability flag and prevents - * it from being set again for some time. */ -bool -rconn_is_connectivity_questionable(struct rconn *rconn) -{ - bool questionable = rconn->questionable_connectivity; - rconn->questionable_connectivity = false; - return questionable; -} - /* Returns the total number of packets successfully received by the underlying * vconn. */ unsigned int @@ -1012,9 +981,6 @@ disconnect(struct rconn *rc, int error) } rc->backoff_deadline = now + rc->backoff; state_transition(rc, S_BACKOFF); - if (now - rc->last_connected > 60) { - question_connectivity(rc); - } } else { rc->last_disconnected = time_now(); rconn_disconnect(rc); @@ -1080,16 +1046,6 @@ state_transition(struct rconn *rc, enum state state) rc->state_entered = time_now(); } -static void -question_connectivity(struct rconn *rc) -{ - time_t now = time_now(); - if (now - rc->last_questioned > 60) { - rc->questionable_connectivity = true; - rc->last_questioned = now; - } -} - static void copy_to_monitor(struct rconn *rc, const struct ofpbuf *b) { diff --git a/lib/rconn.h b/lib/rconn.h index 8579399d..7bc2af8f 100644 --- a/lib/rconn.h +++ b/lib/rconn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,7 +70,6 @@ bool rconn_is_alive(const struct rconn *); bool rconn_is_connected(const struct rconn *); bool rconn_is_admitted(const struct rconn *); int rconn_failure_duration(const struct rconn *); -bool rconn_is_connectivity_questionable(struct rconn *); uint32_t rconn_get_remote_ip(const struct rconn *); uint16_t rconn_get_remote_port(const struct rconn *); diff --git a/ofproto/automake.mk b/ofproto/automake.mk index c6cb9dd4..6484a269 100644 --- a/ofproto/automake.mk +++ b/ofproto/automake.mk @@ -9,8 +9,6 @@ noinst_LIBRARIES += ofproto/libofproto.a ofproto_libofproto_a_SOURCES = \ ofproto/collectors.c \ ofproto/collectors.h \ - ofproto/discovery.c \ - ofproto/discovery.h \ ofproto/fail-open.c \ ofproto/fail-open.h \ ofproto/in-band.c \ diff --git a/ofproto/discovery.c b/ofproto/discovery.c deleted file mode 100644 index ba489ffd..00000000 --- a/ofproto/discovery.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "discovery.h" -#include -#include -#include -#include -#include -#include -#include -#include "dhcp-client.h" -#include "dhcp.h" -#include "dpif.h" -#include "netdev.h" -#include "openflow/openflow.h" -#include "packets.h" -#include "stream-ssl.h" -#include "vlog.h" - -VLOG_DEFINE_THIS_MODULE(discovery); - -struct discovery { - char *dpif_name; - char *re; - bool update_resolv_conf; - regex_t *regex; - struct dhclient *dhcp; - int n_changes; -}; - -static void modify_dhcp_request(struct dhcp_msg *, void *aux); -static bool validate_dhcp_offer(const struct dhcp_msg *, void *aux); - -static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60); - -int -discovery_create(const char *re, bool update_resolv_conf, - struct dpif *dpif, struct discovery **discoveryp) -{ - struct discovery *d; - char local_name[IF_NAMESIZE]; - int error; - - d = xzalloc(sizeof *d); - - d->dpif_name = xstrdup(dpif_base_name(dpif)); - - /* Controller regular expression. */ - error = discovery_set_accept_controller_re(d, re); - if (error) { - goto error_free; - } - d->update_resolv_conf = update_resolv_conf; - - /* Initialize DHCP client. */ - error = dpif_port_get_name(dpif, ODPP_LOCAL, - local_name, sizeof local_name); - if (error) { - VLOG_ERR("%s: failed to query datapath local port: %s", - d->dpif_name, strerror(error)); - goto error_regfree; - } - error = dhclient_create(local_name, modify_dhcp_request, - validate_dhcp_offer, d, &d->dhcp); - if (error) { - VLOG_ERR("%s: failed to initialize DHCP client: %s", - d->dpif_name, strerror(error)); - goto error_regfree; - } - dhclient_set_max_timeout(d->dhcp, 3); - dhclient_init(d->dhcp, 0); - - *discoveryp = d; - return 0; - -error_regfree: - regfree(d->regex); - free(d->regex); -error_free: - free(d->dpif_name); - free(d); - *discoveryp = 0; - return error; -} - -void -discovery_destroy(struct discovery *d) -{ - if (d) { - free(d->re); - regfree(d->regex); - free(d->regex); - dhclient_destroy(d->dhcp); - free(d->dpif_name); - free(d); - } -} - -bool -discovery_get_update_resolv_conf(const struct discovery *d) -{ - return d->update_resolv_conf; -} - -void -discovery_set_update_resolv_conf(struct discovery *d, - bool update_resolv_conf) -{ - d->update_resolv_conf = update_resolv_conf; -} - -const char * -discovery_get_accept_controller_re(const struct discovery *d) -{ - return d->re; -} - -int -discovery_set_accept_controller_re(struct discovery *d, const char *re_) -{ - regex_t *regex; - int error; - char *re; - - re = (!re_ ? xstrdup(stream_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*") - : re_[0] == '^' ? xstrdup(re_) : xasprintf("^%s", re_)); - regex = xmalloc(sizeof *regex); - error = regcomp(regex, re, REG_NOSUB | REG_EXTENDED); - if (error) { - size_t length = regerror(error, regex, NULL, 0); - char *buffer = xmalloc(length); - regerror(error, regex, buffer, length); - VLOG_WARN("%s: %s: %s", d->dpif_name, re, buffer); - free(buffer); - free(regex); - free(re); - return EINVAL; - } else { - if (d->regex) { - regfree(d->regex); - free(d->regex); - } - free(d->re); - - d->regex = regex; - d->re = re; - return 0; - } -} - -void -discovery_question_connectivity(struct discovery *d) -{ - if (d->dhcp) { - dhclient_force_renew(d->dhcp, 15); - } -} - -bool -discovery_run(struct discovery *d, char **controller_name) -{ - if (!d->dhcp) { - *controller_name = NULL; - return true; - } - - dhclient_run(d->dhcp); - if (!dhclient_changed(d->dhcp)) { - return false; - } - - dhclient_configure_netdev(d->dhcp); - if (d->update_resolv_conf) { - dhclient_update_resolv_conf(d->dhcp); - } - - if (dhclient_is_bound(d->dhcp)) { - *controller_name = dhcp_msg_get_string(dhclient_get_config(d->dhcp), - DHCP_CODE_OFP_CONTROLLER_VCONN); - VLOG_INFO("%s: discovered controller %s", - d->dpif_name, *controller_name); - d->n_changes++; - } else { - *controller_name = NULL; - if (d->n_changes) { - VLOG_INFO("%s: discovered controller no longer available", - d->dpif_name); - d->n_changes++; - } - } - return true; -} - -void -discovery_wait(struct discovery *d) -{ - if (d->dhcp) { - dhclient_wait(d->dhcp); - } -} - -static void -modify_dhcp_request(struct dhcp_msg *msg, void *aux OVS_UNUSED) -{ - dhcp_msg_put_string(msg, DHCP_CODE_VENDOR_CLASS, "OpenFlow"); -} - -static bool -validate_dhcp_offer(const struct dhcp_msg *msg, void *d_) -{ - const struct discovery *d = d_; - char *vconn_name; - bool accept; - - vconn_name = dhcp_msg_get_string(msg, DHCP_CODE_OFP_CONTROLLER_VCONN); - if (!vconn_name) { - VLOG_WARN_RL(&rl, "%s: rejecting DHCP offer missing controller vconn", - d->dpif_name); - return false; - } - accept = !regexec(d->regex, vconn_name, 0, NULL, 0); - if (!accept) { - VLOG_WARN_RL(&rl, "%s: rejecting controller vconn that fails to " - "match %s", d->dpif_name, d->re); - } - free(vconn_name); - return accept; -} diff --git a/ofproto/discovery.h b/ofproto/discovery.h deleted file mode 100644 index 999a603f..00000000 --- a/ofproto/discovery.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DISCOVERY_H -#define DISCOVERY_H 1 - -#include - -struct dpif; -struct discovery; -struct settings; - -int discovery_create(const char *accept_controller_re, bool update_resolv_conf, - struct dpif *, struct discovery **); -void discovery_destroy(struct discovery *); -bool discovery_get_update_resolv_conf(const struct discovery *); -void discovery_set_update_resolv_conf(struct discovery *, - bool update_resolv_conf); -const char *discovery_get_accept_controller_re(const struct discovery *); -int discovery_set_accept_controller_re(struct discovery *, const char *re); -void discovery_question_connectivity(struct discovery *); -bool discovery_run(struct discovery *, char **controller_name); -void discovery_wait(struct discovery *); - -#endif /* discovery.h */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index ffeb9524..f4b64f88 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -27,7 +27,6 @@ #include "byte-order.h" #include "classifier.h" #include "coverage.h" -#include "discovery.h" #include "dpif.h" #include "dynamic-string.h" #include "fail-open.h" @@ -332,7 +331,6 @@ struct ofconn { /* type == OFCONN_PRIMARY only. */ enum nx_role role; /* Role. */ struct hmap_node hmap_node; /* In struct ofproto's "controllers" map. */ - struct discovery *discovery; /* Controller discovery object, if enabled. */ enum ofproto_band band; /* In-band or out-of-band? */ }; @@ -544,81 +542,47 @@ ofproto_set_datapath_id(struct ofproto *p, uint64_t datapath_id) } } -static bool -is_discovery_controller(const struct ofproto_controller *c) -{ - return !strcmp(c->target, "discover"); -} - -static bool -is_in_band_controller(const struct ofproto_controller *c) -{ - return is_discovery_controller(c) || c->band == OFPROTO_IN_BAND; -} - /* Creates a new controller in 'ofproto'. Some of the settings are initially * drawn from 'c', but update_controller() needs to be called later to finish * the new ofconn's configuration. */ static void add_controller(struct ofproto *ofproto, const struct ofproto_controller *c) { - struct discovery *discovery; + char *name = ofconn_make_name(ofproto, c->target); struct ofconn *ofconn; - if (is_discovery_controller(c)) { - int error = discovery_create(c->accept_re, c->update_resolv_conf, - ofproto->dpif, &discovery); - if (error) { - return; - } - } else { - discovery = NULL; - } - ofconn = ofconn_create(ofproto, rconn_create(5, 8), OFCONN_PRIMARY); ofconn->pktbuf = pktbuf_create(); ofconn->miss_send_len = OFP_DEFAULT_MISS_SEND_LEN; - if (discovery) { - ofconn->discovery = discovery; - } else { - char *name = ofconn_make_name(ofproto, c->target); - rconn_connect(ofconn->rconn, c->target, name); - free(name); - } + rconn_connect(ofconn->rconn, c->target, name); hmap_insert(&ofproto->controllers, &ofconn->hmap_node, hash_string(c->target, 0)); + + free(name); } /* Reconfigures 'ofconn' to match 'c'. This function cannot update an ofconn's - * target or turn discovery on or off (these are done by creating new ofconns - * and deleting old ones), but it can update the rest of an ofconn's - * settings. */ + * target (this is done by creating new ofconns and deleting old ones), but it + * can update the rest of an ofconn's settings. */ static void update_controller(struct ofconn *ofconn, const struct ofproto_controller *c) { int probe_interval; - ofconn->band = (is_in_band_controller(c) - ? OFPROTO_IN_BAND : OFPROTO_OUT_OF_BAND); + ofconn->band = c->band; rconn_set_max_backoff(ofconn->rconn, c->max_backoff); probe_interval = c->probe_interval ? MAX(c->probe_interval, 5) : 0; rconn_set_probe_interval(ofconn->rconn, probe_interval); - if (ofconn->discovery) { - discovery_set_update_resolv_conf(ofconn->discovery, - c->update_resolv_conf); - discovery_set_accept_controller_re(ofconn->discovery, c->accept_re); - } - ofconn_set_rate_limit(ofconn, c->rate_limit, c->burst_limit); } static const char * ofconn_get_target(const struct ofconn *ofconn) { - return ofconn->discovery ? "discover" : rconn_get_target(ofconn->rconn); + return rconn_get_target(ofconn->rconn); } static struct ofconn * @@ -641,7 +605,6 @@ update_in_band_remotes(struct ofproto *ofproto) const struct ofconn *ofconn; struct sockaddr_in *addrs; size_t max_addrs, n_addrs; - bool discovery; size_t i; /* Allocate enough memory for as many remotes as we could possibly have. */ @@ -650,7 +613,6 @@ update_in_band_remotes(struct ofproto *ofproto) n_addrs = 0; /* Add all the remotes. */ - discovery = false; HMAP_FOR_EACH (ofconn, hmap_node, &ofproto->controllers) { struct sockaddr_in *sin = &addrs[n_addrs]; @@ -663,20 +625,13 @@ update_in_band_remotes(struct ofproto *ofproto) sin->sin_port = rconn_get_remote_port(ofconn->rconn); n_addrs++; } - if (ofconn->discovery) { - discovery = true; - } } for (i = 0; i < ofproto->n_extra_remotes; i++) { addrs[n_addrs++] = ofproto->extra_in_band_remotes[i]; } - /* Create or update or destroy in-band. - * - * Ordinarily we only enable in-band if there's at least one remote - * address, but discovery needs the in-band rules for DHCP to be installed - * even before we know any remote addresses. */ - if (n_addrs || discovery) { + /* Create or update or destroy in-band. */ + if (n_addrs) { if (!ofproto->in_band) { in_band_create(ofproto, ofproto->dpif, &ofproto->in_band); } @@ -738,7 +693,7 @@ ofproto_set_controllers(struct ofproto *p, for (i = 0; i < n_controllers; i++) { const struct ofproto_controller *c = &controllers[i]; - if (!vconn_verify_name(c->target) || !strcmp(c->target, "discover")) { + if (!vconn_verify_name(c->target)) { if (!find_controller_by_target(p, c->target)) { add_controller(p, c); } @@ -1821,7 +1776,6 @@ ofconn_destroy(struct ofconn *ofconn) if (ofconn->type == OFCONN_PRIMARY) { hmap_remove(&ofconn->ofproto->controllers, &ofconn->hmap_node); } - discovery_destroy(ofconn->discovery); list_remove(&ofconn->node); rconn_destroy(ofconn->rconn); @@ -1838,23 +1792,6 @@ ofconn_run(struct ofconn *ofconn) int iteration; size_t i; - if (ofconn->discovery) { - char *controller_name; - if (rconn_is_connectivity_questionable(ofconn->rconn)) { - discovery_question_connectivity(ofconn->discovery); - } - if (discovery_run(ofconn->discovery, &controller_name)) { - if (controller_name) { - char *ofconn_name = ofconn_make_name(p, controller_name); - rconn_connect(ofconn->rconn, controller_name, ofconn_name); - free(ofconn_name); - free(controller_name); - } else { - rconn_disconnect(ofconn->rconn); - } - } - } - for (i = 0; i < N_SCHEDULERS; i++) { pinsched_run(ofconn->schedulers[i], do_send_packet_in, ofconn); } @@ -1877,7 +1814,7 @@ ofconn_run(struct ofconn *ofconn) } } - if (!ofconn->discovery && !rconn_is_alive(ofconn->rconn)) { + if (!rconn_is_alive(ofconn->rconn)) { ofconn_destroy(ofconn); } } @@ -1887,9 +1824,6 @@ ofconn_wait(struct ofconn *ofconn) { int i; - if (ofconn->discovery) { - discovery_wait(ofconn->discovery); - } for (i = 0; i < N_SCHEDULERS; i++) { pinsched_wait(ofconn->schedulers[i]); } diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index a32b9b91..93763b5c 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,10 +81,6 @@ struct ofproto_controller { int probe_interval; /* Max idle time before probing, in seconds. */ enum ofproto_band band; /* In-band or out-of-band? */ - /* Discovery options. */ - char *accept_re; /* Regexp for acceptable controllers. */ - bool update_resolv_conf; /* Update /etc/resolv.conf? */ - /* OpenFlow packet-in rate-limiting. */ int rate_limit; /* Max packet-in rate in packets per second. */ int burst_limit; /* Limit on accumulating packet credits. */ diff --git a/tests/.gitignore b/tests/.gitignore index 90f17378..a7fcf17c 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -9,7 +9,6 @@ /test-byte-order /test-classifier /test-csum -/test-dhcp-client /test-file_name /test-flows /test-hash diff --git a/tests/automake.mk b/tests/automake.mk index e2d3388a..7872d21a 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -68,7 +68,6 @@ lcov_wrappers = \ tests/lcov/test-byte-order \ tests/lcov/test-classifier \ tests/lcov/test-csum \ - tests/lcov/test-dhcp-client \ tests/lcov/test-file_name \ tests/lcov/test-flows \ tests/lcov/test-hash \ @@ -121,7 +120,6 @@ valgrind_wrappers = \ tests/valgrind/test-byte-order \ tests/valgrind/test-classifier \ tests/valgrind/test-csum \ - tests/valgrind/test-dhcp-client \ tests/valgrind/test-file_name \ tests/valgrind/test-flows \ tests/valgrind/test-hash \ @@ -278,10 +276,6 @@ tests_test_strtok_r_SOURCES = tests/test-strtok_r.c noinst_PROGRAMS += tests/test-type-props tests_test_type_props_SOURCES = tests/test-type-props.c -noinst_PROGRAMS += tests/test-dhcp-client -tests_test_dhcp_client_SOURCES = tests/test-dhcp-client.c -tests_test_dhcp_client_LDADD = lib/libopenvswitch.a - noinst_PROGRAMS += tests/test-uuid tests_test_uuid_SOURCES = tests/test-uuid.c tests_test_uuid_LDADD = lib/libopenvswitch.a diff --git a/tests/test-dhcp-client.c b/tests/test-dhcp-client.c deleted file mode 100644 index 991edd45..00000000 --- a/tests/test-dhcp-client.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "dhcp-client.h" -#include -#include -#include -#include -#include "command-line.h" -#include "dhcp.h" -#include "fatal-signal.h" -#include "poll-loop.h" -#include "util.h" -#include "vlog.h" - -/* --request-ip: IP address to request from server. If zero, then do not - * request a specific IP address. */ -static struct in_addr request_ip; - -/* --vendor-class: Vendor class string to include in request. If null, no - * vendor class string is included. */ -static const char *vendor_class; - -/* --no-resolv-conf: Update /etc/resolv.conf to match DHCP reply? */ -static bool update_resolv_conf = true; - -static void parse_options(int argc, char *argv[]); -static void usage(void); -static void release(void *cli_); -static void modify_dhcp_request(struct dhcp_msg *, void *aux); - -int -main(int argc, char *argv[]) -{ - struct dhclient *cli; - int error; - - set_program_name(argv[0]); - parse_options(argc, argv); - - argc -= optind; - argv += optind; - if (argc != 1) { - ovs_fatal(0, "exactly one non-option argument required; " - "use --help for help"); - } - - error = dhclient_create(argv[0], modify_dhcp_request, NULL, NULL, &cli); - if (error) { - ovs_fatal(error, "dhclient_create failed"); - } - dhclient_init(cli, request_ip.s_addr); - fatal_signal_add_hook(release, NULL, cli, true); - - for (;;) { - dhclient_run(cli); - if (dhclient_changed(cli)) { - dhclient_configure_netdev(cli); - if (update_resolv_conf) { - dhclient_update_resolv_conf(cli); - } - } - dhclient_wait(cli); - poll_block(); - } -} - -static void -release(void *cli_) -{ - struct dhclient *cli = cli_; - dhclient_release(cli); - if (dhclient_changed(cli)) { - dhclient_configure_netdev(cli); - } -} - -static void -modify_dhcp_request(struct dhcp_msg *msg, void *aux OVS_UNUSED) -{ - if (vendor_class) { - dhcp_msg_put_string(msg, DHCP_CODE_VENDOR_CLASS, vendor_class); - } -} - -static void -parse_options(int argc, char *argv[]) -{ - enum { - OPT_REQUEST_IP = UCHAR_MAX + 1, - OPT_VENDOR_CLASS, - OPT_NO_RESOLV_CONF - }; - static struct option long_options[] = { - {"request-ip", required_argument, 0, OPT_REQUEST_IP }, - {"vendor-class", required_argument, 0, OPT_VENDOR_CLASS }, - {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF}, - {"verbose", optional_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {0, 0, 0, 0}, - }; - char *short_options = long_options_to_short_options(long_options); - - for (;;) { - int c; - - c = getopt_long(argc, argv, short_options, long_options, NULL); - if (c == -1) { - break; - } - - switch (c) { - case OPT_REQUEST_IP: - if (!inet_aton(optarg, &request_ip)) { - ovs_fatal(0, - "--request-ip argument is not a valid IP address"); - } - break; - - case OPT_VENDOR_CLASS: - vendor_class = optarg; - break; - - case OPT_NO_RESOLV_CONF: - update_resolv_conf = false; - break; - - case 'h': - usage(); - - case 'V': - printf("%s %s compiled "__DATE__" "__TIME__"\n", - program_name, VERSION BUILDNR); - exit(EXIT_SUCCESS); - - case 'v': - vlog_set_verbosity(optarg); - break; - - case '?': - exit(EXIT_FAILURE); - - default: - abort(); - } - } - free(short_options); -} - -static void -usage(void) -{ - printf("%s: standalone program for testing Open vSwitch DHCP client.\n" - "usage: %s [OPTIONS] NETDEV\n" - "where NETDEV is a network device (e.g. eth0).\n" - "\nDHCP options:\n" - " --request-ip=IP request specified IP address (default:\n" - " do not request a specific IP)\n" - " --vendor-class=STRING use STRING as vendor class; use\n" - " OpenFlow to imitate ovs-openflowd\n" - " --no-resolv-conf do not update /etc/resolv.conf\n", - program_name, program_name); - vlog_usage(); - printf("\nOther options:\n" - " -h, --help display this help message\n" - " -V, --version display version information\n"); - exit(EXIT_SUCCESS); -} - diff --git a/utilities/.gitignore b/utilities/.gitignore index 56b3e73b..a2ef09b4 100644 --- a/utilities/.gitignore +++ b/utilities/.gitignore @@ -7,8 +7,6 @@ /ovs-cfg-mod.8 /ovs-controller /ovs-controller.8 -/ovs-discover -/ovs-discover.8 /ovs-dpctl /ovs-dpctl.8 /ovs-ofctl diff --git a/utilities/automake.mk b/utilities/automake.mk index b267c02f..1233762f 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -1,7 +1,6 @@ bin_PROGRAMS += \ utilities/ovs-appctl \ utilities/ovs-controller \ - utilities/ovs-discover \ utilities/ovs-dpctl \ utilities/ovs-ofctl \ utilities/ovs-openflowd \ @@ -18,7 +17,6 @@ noinst_SCRIPTS += utilities/ovs-pki-cgi utilities/ovs-parse-leaks EXTRA_DIST += \ utilities/ovs-appctl.8.in \ utilities/ovs-controller.8.in \ - utilities/ovs-discover.8.in \ utilities/ovs-dpctl.8.in \ utilities/ovs-ofctl.8.in \ utilities/ovs-openflowd.8.in \ @@ -40,7 +38,6 @@ EXTRA_DIST += \ DISTCLEANFILES += \ utilities/ovs-appctl.8 \ utilities/ovs-controller.8 \ - utilities/ovs-discover.8 \ utilities/ovs-dpctl.8 \ utilities/ovs-ofctl.8 \ utilities/ovs-openflowd.8 \ @@ -59,7 +56,6 @@ DISTCLEANFILES += \ man_MANS += \ utilities/ovs-appctl.8 \ utilities/ovs-controller.8 \ - utilities/ovs-discover.8 \ utilities/ovs-dpctl.8 \ utilities/ovs-ofctl.8 \ utilities/ovs-openflowd.8 \ @@ -77,9 +73,6 @@ utilities_ovs_appctl_LDADD = lib/libopenvswitch.a utilities_ovs_controller_SOURCES = utilities/ovs-controller.c utilities_ovs_controller_LDADD = lib/libopenvswitch.a $(SSL_LIBS) -utilities_ovs_discover_SOURCES = utilities/ovs-discover.c -utilities_ovs_discover_LDADD = lib/libopenvswitch.a - utilities_ovs_dpctl_SOURCES = utilities/ovs-dpctl.c utilities_ovs_dpctl_LDADD = lib/libopenvswitch.a diff --git a/utilities/ovs-appctl.8.in b/utilities/ovs-appctl.8.in index b1f2ab6e..86d5a8b0 100644 --- a/utilities/ovs-appctl.8.in +++ b/utilities/ovs-appctl.8.in @@ -168,5 +168,4 @@ white space. .BR ovs\-vswitchd (8), .BR ovs\-openflowd (8), .BR ovs\-controller (8), -.BR ovs\-brcompatd (8), -.BR ovs\-discover (8). +.BR ovs\-brcompatd (8). diff --git a/utilities/ovs-discover.8.in b/utilities/ovs-discover.8.in deleted file mode 100644 index c9bbbb55..00000000 --- a/utilities/ovs-discover.8.in +++ /dev/null @@ -1,118 +0,0 @@ -.TH ovs\-discover 8 "May 2008" "Open vSwitch" "Open vSwitch Manual" -.ds PN ovs\-discover - -.SH NAME -ovs\-discover \- controller discovery utility - -.SH SYNOPSIS -.B ovs\-discover -[\fIoptions\fR] \fInetdev\fR [\fInetdev\fR...] - -.SH DESCRIPTION -The \fBovs\-discover\fR program attempts to discover the location of -an OpenFlow controller on one of the network devices listed on the -command line. It repeatedly broadcasts a DHCP request with vendor -class identifier \fBOpenFlow\fR on each network device until it -receives an acceptable DHCP response. It will accept any valid DHCP -reply that has the same vendor class identifier and includes a -vendor-specific option with code 1 whose contents are a string -specifying the location of the controller in the same format used on -the \fBovs\-openflowd\fR command line (e.g. \fBssl:192.168.0.1\fR). - -When \fBovs\-discover\fR receives an acceptable response, it prints -the details of the response on \fBstdout\fR. Then, by default, it -configures the network device on which the response was received with -the received IP address, netmask, and default gateway, and detaches -itself to the background. - -.SH OPTIONS -.TP -\fB\-\-accept\-vconn=\fIregex\fR -With this option, only controllers whose names match POSIX extended -regular expression \fIregex\fR will be accepted. Specifying -\fBssl:.*\fR for \fIregex\fR, for example, would cause only SSL -controller connections to be accepted. - -The \fIregex\fR is implicitly anchored at the beginning of the -controller location string, as if it begins with \fB^\fR. - -When this option is not given, the default \fIregex\fR is -\fBtcp:.*\fR. -.TP -\fB\-\-exit\-without\-bind\fR -By default, \fBovs\-discover\fR binds the network device that receives -the first acceptable response to the IP address received over DHCP. -With this option, the configuration of the network device is not -changed at all, except to bring it up if it is initially down, and -\fBovs\-discover\fR will exit immediately after it receives an -acceptable DHCP response. - -This option is mutually exclusive with \fB\-\-exit\-after\-bind\fR and -\fB\-\-no\-detach\fR. - -.TP -\fB\-\-exit\-after\-bind\fR -By default, after it receives an acceptable DHCP response, -\fBovs\-discover\fR detaches itself from the foreground session and -runs in the background maintaining the DHCP lease as necessary. With -this option, \fBovs\-discover\fR will exit immediately after it -receives an acceptable DHCP response and configures the network device -with the received IP address. The address obtained via DHCP could -therefore be used past the expiration of its lease. - -This option is mutually exclusive with \fB\-\-exit\-without\-bind\fR and -\fB\-\-no\-detach\fR. - -.TP -\fB\-\-no\-detach\fR -By default, \fBovs\-discover\fR runs in the foreground until it obtains -an acceptable DHCP response, then it detaches itself from the -foreground session and run as a background process. This option -prevents \fBovs\-discover\fR from detaching, causing it to run in the -foreground even after it obtains a DHCP response. - -This option is mutually exclusive with \fB\-\-exit\-without\-bind\fR and -\fB\-\-exit\-after\-bind\fR. - -.TP -\fB\-\-pidfile\fR[\fB=\fIpidfile\fR] -Causes a file (by default, \fBovs\-discover.pid\fR) to be created indicating -the PID of the running process. If \fIpidfile\fR is not specified, or -if it does not begin with \fB/\fR, then it is created in -\fB@RUNDIR@\fR. - -The \fIpidfile\fR is created when \fBovs\-discover\fR detaches, so -this this option has no effect when one of \fB\-\-exit\-without\-bind\fR, -\fB\-\-exit\-after\-bind\fR, or \fB\-\-no\-detach\fR is also given. - -.TP -\fB\-\-overwrite\-pidfile\fR -By default, when \fB\-\-pidfile\fR is specified and the specified pidfile -already exists and is locked by a running process, \fBcontroller\fR refuses -to start. Specify \fB\-\-overwrite\-pidfile\fR to cause it to instead -overwrite the pidfile. - -When \fB\-\-pidfile\fR is not specified, this option has no effect. - -.so lib/vlog.man -.so lib/common.man - -.SH BUGS - -If the network devices specified on the command line have been added -to an Open vSwitch datapath with \fBovs\-dpctl add\-if\fR, then controller -discovery will fail because \fBovs\-discover\fR will not be able to -see DHCP responses, even though tools such as \fBtcpdump\fR(8) and -\fBwireshark\fR(1) can see them on the wire. This is because of the -structure of the Linux kernel networking stack, which hands packets -first to programs that listen for all arriving packets, then to -Open vSwitch, then to programs that listen for a specific kind of packet. -Open vSwitch consumes all the packets handed to it, so tools like -\fBtcpdump\fR that look at all packets will see packets arriving on -Open vSwitch interfaces, but \fRovs\-discover\fR, which listens only for -arriving IP packets, will not. - -.SH "SEE ALSO" - -.BR ovs\-openflowd (8), -.BR ovs\-pki (8) diff --git a/utilities/ovs-discover.c b/utilities/ovs-discover.c deleted file mode 100644 index 534dd774..00000000 --- a/utilities/ovs-discover.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "command-line.h" -#include "daemon.h" -#include "dhcp-client.h" -#include "dhcp.h" -#include "dirs.h" -#include "dynamic-string.h" -#include "fatal-signal.h" -#include "netdev.h" -#include "poll-loop.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" -#include "vlog.h" - -VLOG_DEFINE_THIS_MODULE(ovs_discover); - -struct iface { - const char *name; - struct dhclient *dhcp; -}; - -/* The interfaces that we serve. */ -static struct iface *ifaces; -static int n_ifaces; - -/* --accept-vconn: Regular expression specifying the class of controller vconns - * that we will accept during autodiscovery. */ -static const char *accept_controller_re = "tcp:.*"; -static regex_t accept_controller_regex; - -/* --exit-without-bind: Exit after discovering the controller, without binding - * the network device to an IP address? */ -static bool exit_without_bind; - -/* --exit-after-bind: Exit after discovering the controller, after binding the - * network device to an IP address? */ -static bool exit_after_bind; - -static bool iface_init(struct iface *, const char *netdev_name); -static void release_ifaces(void *aux OVS_UNUSED); - -static void parse_options(int argc, char *argv[]); -static void usage(void) NO_RETURN; - -static void modify_dhcp_request(struct dhcp_msg *, void *aux); -static bool validate_dhcp_offer(const struct dhcp_msg *, void *aux); - -int -main(int argc, char *argv[]) -{ - struct unixctl_server *unixctl; - int retval; - int i; - - proctitle_init(argc, argv); - set_program_name(argv[0]); - parse_options(argc, argv); - - argc -= optind; - argv += optind; - if (argc < 1) { - ovs_fatal(0, "need at least one non-option argument; " - "use --help for usage"); - } - - ifaces = xmalloc(argc * sizeof *ifaces); - n_ifaces = 0; - for (i = 0; i < argc; i++) { - if (iface_init(&ifaces[n_ifaces], argv[i])) { - n_ifaces++; - } - } - if (!n_ifaces) { - ovs_fatal(0, "failed to initialize any DHCP clients"); - } - - for (i = 0; i < n_ifaces; i++) { - struct iface *iface = &ifaces[i]; - dhclient_init(iface->dhcp, 0); - } - fatal_signal_add_hook(release_ifaces, NULL, NULL, true); - - retval = regcomp(&accept_controller_regex, accept_controller_re, - REG_NOSUB | REG_EXTENDED); - if (retval) { - size_t length = regerror(retval, &accept_controller_regex, NULL, 0); - char *buffer = xmalloc(length); - regerror(retval, &accept_controller_regex, buffer, length); - ovs_fatal(0, "%s: %s", accept_controller_re, buffer); - } - - retval = unixctl_server_create(NULL, &unixctl); - if (retval) { - exit(EXIT_FAILURE); - } - - die_if_already_running(); - - signal(SIGPIPE, SIG_IGN); - for (;;) { - for (i = 0; i < n_ifaces; i++) { - struct iface *iface = &ifaces[i]; - dhclient_run(iface->dhcp); - if (dhclient_changed(iface->dhcp)) { - bool is_bound = dhclient_is_bound(iface->dhcp); - int j; - - /* Configure network device. */ - if (!exit_without_bind) { - dhclient_configure_netdev(iface->dhcp); - dhclient_update_resolv_conf(iface->dhcp); - } - - if (is_bound) { - static bool detached = false; - struct ds ds; - - /* Disable timeout, since discovery was successful. */ - time_alarm(0); - - /* Print discovered parameters. */ - ds_init(&ds); - dhcp_msg_to_string(dhclient_get_config(iface->dhcp), - true, &ds); - fputs(ds_cstr(&ds), stdout); - putchar('\n'); - fflush(stdout); - ds_destroy(&ds); - - /* Exit if the user requested it. */ - if (exit_without_bind) { - VLOG_DBG("exiting because of successful binding on %s " - "and --exit-without-bind specified", - iface->name); - exit(0); - } - if (exit_after_bind) { - VLOG_DBG("exiting because of successful binding on %s " - "and --exit-after-bind specified", - iface->name); - exit(0); - } - - /* Detach into background, if we haven't already. */ - if (!detached) { - detached = true; - daemonize(); - } - } - - /* We only want an address on a single one of our interfaces. - * So: if we have an address on this interface, stop looking - * for one on the others; if we don't have an address on this - * interface, start looking everywhere. */ - for (j = 0; j < n_ifaces; j++) { - struct iface *if2 = &ifaces[j]; - if (iface != if2) { - if (is_bound) { - dhclient_release(if2->dhcp); - } else { - dhclient_init(if2->dhcp, 0); - } - } - } - } - } - unixctl_server_run(unixctl); - for (i = 0; i < n_ifaces; i++) { - struct iface *iface = &ifaces[i]; - dhclient_wait(iface->dhcp); - } - unixctl_server_wait(unixctl); - poll_block(); - } - - return 0; -} - -static bool -iface_init(struct iface *iface, const char *netdev_name) -{ - int retval; - - iface->name = netdev_name; - iface->dhcp = NULL; - - if (exit_after_bind) { - /* Bring this interface up permanently, so that the bound address - * persists past program termination. */ - struct netdev *netdev; - - retval = netdev_open_default(iface->name, &netdev); - if (retval) { - ovs_error(retval, "Could not open %s device", iface->name); - return false; - } - retval = netdev_turn_flags_on(netdev, NETDEV_UP, true); - if (retval) { - ovs_error(retval, "Could not bring %s device up", iface->name); - return false; - } - netdev_close(netdev); - } - - retval = dhclient_create(iface->name, modify_dhcp_request, - validate_dhcp_offer, NULL, &iface->dhcp); - if (retval) { - ovs_error(retval, "%s: failed to initialize DHCP client", iface->name); - return false; - } - - return true; -} - -static void -release_ifaces(void *aux OVS_UNUSED) -{ - int i; - - for (i = 0; i < n_ifaces; i++) { - struct dhclient *dhcp = ifaces[i].dhcp; - dhclient_release(dhcp); - if (dhclient_changed(dhcp)) { - dhclient_configure_netdev(dhcp); - } - } -} - -static void -modify_dhcp_request(struct dhcp_msg *msg, void *aux OVS_UNUSED) -{ - dhcp_msg_put_string(msg, DHCP_CODE_VENDOR_CLASS, "OpenFlow"); -} - -static bool -validate_dhcp_offer(const struct dhcp_msg *msg, void *aux OVS_UNUSED) -{ - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60); - char *vconn_name; - bool accept; - - vconn_name = dhcp_msg_get_string(msg, DHCP_CODE_OFP_CONTROLLER_VCONN); - if (!vconn_name) { - VLOG_WARN_RL(&rl, "rejecting DHCP offer missing controller vconn"); - return false; - } - accept = !regexec(&accept_controller_regex, vconn_name, 0, NULL, 0); - free(vconn_name); - return accept; -} - -static void -parse_options(int argc, char *argv[]) -{ - enum { - OPT_ACCEPT_VCONN = UCHAR_MAX + 1, - OPT_EXIT_WITHOUT_BIND, - OPT_EXIT_AFTER_BIND, - OPT_NO_DETACH, - VLOG_OPTION_ENUMS, - DAEMON_OPTION_ENUMS - }; - static struct option long_options[] = { - {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN}, - {"exit-without-bind", no_argument, 0, OPT_EXIT_WITHOUT_BIND}, - {"exit-after-bind", no_argument, 0, OPT_EXIT_AFTER_BIND}, - {"no-detach", no_argument, 0, OPT_NO_DETACH}, - {"timeout", required_argument, 0, 't'}, - {"pidfile", optional_argument, 0, OPT_PIDFILE}, - {"overwrite-pidfile", no_argument, 0, OPT_OVERWRITE_PIDFILE}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - VLOG_LONG_OPTIONS, - {0, 0, 0, 0}, - }; - char *short_options = long_options_to_short_options(long_options); - bool detach_after_bind = true; - - for (;;) { - unsigned long int timeout; - int c; - - c = getopt_long(argc, argv, short_options, long_options, NULL); - if (c == -1) { - break; - } - - switch (c) { - case OPT_ACCEPT_VCONN: - accept_controller_re = (optarg[0] == '^' - ? optarg - : xasprintf("^%s", optarg)); - break; - - case OPT_EXIT_WITHOUT_BIND: - exit_without_bind = true; - break; - - case OPT_EXIT_AFTER_BIND: - exit_after_bind = true; - break; - - case OPT_NO_DETACH: - detach_after_bind = false; - break; - - case OPT_PIDFILE: - set_pidfile(optarg); - break; - - case OPT_OVERWRITE_PIDFILE: - ignore_existing_pidfile(); - break; - - case 't': - timeout = strtoul(optarg, NULL, 10); - if (timeout <= 0) { - ovs_fatal(0, "value %s on -t or --timeout is not at least 1", - optarg); - } else { - time_alarm(timeout); - } - signal(SIGALRM, SIG_DFL); - break; - - case 'h': - usage(); - - case 'V': - OVS_PRINT_VERSION(0, 0); - exit(EXIT_SUCCESS); - - VLOG_OPTION_HANDLERS - - case '?': - exit(EXIT_FAILURE); - - default: - abort(); - } - } - free(short_options); - - if ((exit_without_bind + exit_after_bind + !detach_after_bind) > 1) { - ovs_fatal(0, "--exit-without-bind, --exit-after-bind, and --no-detach " - "are mutually exclusive"); - } - if (detach_after_bind) { - set_detach(); - } -} - -static void -usage(void) -{ - printf("%s: a tool for discovering OpenFlow controllers.\n" - "usage: %s [OPTIONS] NETDEV [NETDEV...]\n" - "where each NETDEV is a network device on which to perform\n" - "controller discovery.\n" - "\nOrdinarily, ovs-discover runs in the foreground until it\n" - "obtains an IP address and discovers an OpenFlow controller via\n" - "DHCP, then it prints information about the controller to stdout\n" - "and detaches to the background to maintain the IP address lease.\n" - "\nNetworking options:\n" - " --accept-vconn=REGEX accept matching discovered controllers\n" - " --exit-without-bind exit after discovery, without binding\n" - " --exit-after-bind exit after discovery, after binding\n" - " --no-detach do not detach after discovery\n", - program_name, program_name); - vlog_usage(); - printf("\nOther options:\n" - " -t, --timeout=SECS give up discovery after SECS seconds\n" - " --pidfile[=FILE] create pidfile (default: %s/%s.pid)\n" - " --overwrite-pidfile with --pidfile, start even if already " - "running\n" - " -h, --help display this help message\n" - " -V, --version display version information\n", - ovs_rundir(), program_name); - exit(EXIT_SUCCESS); -} diff --git a/utilities/ovs-openflowd.8.in b/utilities/ovs-openflowd.8.in index 9dec805e..c22ed918 100644 --- a/utilities/ovs-openflowd.8.in +++ b/utilities/ovs-openflowd.8.in @@ -9,7 +9,7 @@ ovs\-openflowd \- OpenFlow switch implementation . .SH SYNOPSIS .B ovs\-openflowd -[\fIoptions\fR] \fIdatapath\fR [\fIcontroller\fR\&...] +[\fIoptions\fR] \fIdatapath\fR \fIcontroller\fR\&... . .SH DESCRIPTION The \fBovs\-openflowd\fR program implements an OpenFlow switch using a @@ -46,9 +46,6 @@ switch, so more than one controller should be specified only if the controllers are themselves designed to coordinate with each other. (The Nicira-defined \fBNXT_ROLE\fR OpenFlow vendor extension may be useful for this.) -.PP -If no \fIcontroller\fR is specified, \fBovs\-openflowd\fR attempts to -discover the location of a controller automatically (see below). . .SS "Contacting Controllers" The OpenFlow switch must be able to contact the OpenFlow controllers @@ -75,82 +72,8 @@ independent networks. .IP In-band control is the default for \fBovs\-openflowd\fR, so no special command-line option is required. -.IP -With in-band control, the location of the controller can be configured -manually or discovered automatically: -. -.RS -.IP "controller discovery" -To make \fBovs\-openflowd\fR discover the location of the controller -automatically, do not specify a controller on the \fBovs\-openflowd\fR -command line. -.IP -In this mode, \fBovs\-openflowd\fR will broadcast a DHCP request with vendor -class identifier \fBOpenFlow\fR across the network devices added to -the datapath with \fBovs\-dpctl add\-if\fR. It will accept any valid DHCP -reply that has the same vendor class identifier and includes a -vendor-specific option with code 1 whose contents are a string -specifying the location of the controller in the same format used on -the \fBovs\-openflowd\fR command line (e.g. \fBssl:192.168.0.1\fR). -.IP -The DHCP reply may also, optionally, include a vendor-specific option -with code 2 whose contents are a string specifying the URI to the base -of the OpenFlow PKI (e.g. \fBhttp://192.168.0.1/openflow/pki\fR). -This URI is used only for bootstrapping the OpenFlow PKI at initial -switch setup; \fBovs\-openflowd\fR does not use it at all. -.IP -The following ISC DHCP server configuration file assigns the IP -address range 192.168.0.20 through 192.168.0.30 to OpenFlow switches -that follow the switch protocol and addresses 192.168.0.1 through -192.168.0.10 to all other DHCP clients: -.IP -default\-lease\-time 600; -.br -max\-lease\-time 7200; -.br -option space openflow; -.br -option openflow.controller\-vconn code 1 = text; -.br -option openflow.pki\-uri code 2 = text; -.br -class "OpenFlow" { -.br - match if option vendor\-class\-identifier = "OpenFlow"; -.br - vendor\-option\-space openflow; -.br - option openflow.controller\-vconn "tcp:192.168.0.10"; -.br - option openflow.pki\-uri "http://192.168.0.10/openflow/pki"; -.br - option vendor\-class\-identifier "OpenFlow"; -.br -} -.br -subnet 192.168.0.0 netmask 255.255.255.0 { -.br - pool { -.br - allow members of "OpenFlow"; -.br - range 192.168.0.20 192.168.0.30; -.br - } -.br - pool { -.br - deny members of "OpenFlow"; -.br - range 192.168.0.1 192.168.0.10; -.br - } -.br -} -.br -. -.IP "manual configuration" -To configure in-band control manually, specify the location of the + +Specify the location of the controller on the \fBovs\-openflowd\fR command line as the \fIcontroller\fR argument. You must also configure the network device for the OpenFlow ``local port'' to allow \fBovs\-openflowd\fR to connect to that controller. @@ -216,44 +139,6 @@ Set the description of the datapath to \fIdesc\fR, which may contain up to purposes and is not guaranteed to be unique and should not be used as the primary identifier of the datapath. . -.SS "Controller Discovery Options" -.TP -\fB\-\-accept\-vconn=\fIregex\fR -When \fBovs\-openflowd\fR performs controller discovery (see \fBContacting -the Controller\fR, above, for more information about controller -discovery), it validates the controller location obtained via DHCP -with a POSIX extended regular expression. Only controllers whose -names match the regular expression will be accepted. -.IP -The default regular expression is \fBssl:.*\fR (meaning that only SSL -controller connections will be accepted) when any of the SSL -configuration options \fB\-\-private\-key\fR, \fB\-\-certificate\fR, or -\fB\-\-ca\-cert\fR is specified. The default is \fB^tcp:.*\fR otherwise -(meaning that only TCP controller connections will be accepted). -.IP -The \fIregex\fR is implicitly anchored at the beginning of the -controller location string, as if it begins with \fB^\fR. -.IP -When controller discovery is not performed, this option has no effect. -. -.TP -\fB\-\-no\-resolv\-conf\fR -When \fBovs\-openflowd\fR performs controller discovery (see \fBContacting -the Controller\fR, above, for more information about controller -discovery), by default it overwrites the system's -\fB/etc/resolv.conf\fR with domain information and DNS servers -obtained via DHCP. If the location of the controller is specified -using a hostname, rather than an IP address, and the network's DNS -servers ever change, this behavior is essential. But because it also -interferes with any administrator or process that manages -\fB/etc/resolv.conf\fR, when this option is specified, \fBovs\-openflowd\fR -will not modify \fB/etc/resolv.conf\fR. -.IP -\fBovs\-openflowd\fR will only modify \fBresolv.conf\fR if the DHCP response -that it receives specifies one or more DNS servers. -.IP -When controller discovery is not performed, this option has no effect. -. .SS "Networking Options" .TP \fB\-\-datapath\-id=\fIdpid\fR @@ -455,7 +340,6 @@ Causes \fBovs\-openflowd\fR to gracefully terminate. . .BR ovs\-appctl (8), .BR ovs\-controller (8), -.BR ovs\-discover (8), .BR ovs\-dpctl (8), .BR ovs\-ofctl (8), .BR ovs\-pki (8) diff --git a/utilities/ovs-openflowd.c b/utilities/ovs-openflowd.c index 486eae28..d2e0336f 100644 --- a/utilities/ovs-openflowd.c +++ b/utilities/ovs-openflowd.c @@ -216,8 +216,6 @@ parse_options(int argc, char *argv[], struct ofsettings *s) OPT_SW_DESC, OPT_SERIAL_DESC, OPT_DP_DESC, - OPT_ACCEPT_VCONN, - OPT_NO_RESOLV_CONF, OPT_BR_NAME, OPT_FAIL_MODE, OPT_INACTIVITY_PROBE, @@ -244,8 +242,6 @@ parse_options(int argc, char *argv[], struct ofsettings *s) {"sw-desc", required_argument, 0, OPT_SW_DESC}, {"serial-desc", required_argument, 0, OPT_SERIAL_DESC}, {"dp-desc", required_argument, 0, OPT_DP_DESC}, - {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN}, - {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF}, {"config", required_argument, 0, 'F'}, {"br-name", required_argument, 0, OPT_BR_NAME}, {"fail", required_argument, 0, OPT_FAIL_MODE}, @@ -284,8 +280,6 @@ parse_options(int argc, char *argv[], struct ofsettings *s) controller_opts.max_backoff = 8; controller_opts.probe_interval = 5; controller_opts.band = OFPROTO_IN_BAND; - controller_opts.accept_re = NULL; - controller_opts.update_resolv_conf = true; controller_opts.rate_limit = 0; controller_opts.burst_limit = 0; s->unixctl_path = NULL; @@ -337,14 +331,6 @@ parse_options(int argc, char *argv[], struct ofsettings *s) s->dp_desc = optarg; break; - case OPT_ACCEPT_VCONN: - controller_opts.accept_re = optarg; - break; - - case OPT_NO_RESOLV_CONF: - controller_opts.update_resolv_conf = false; - break; - case OPT_FAIL_MODE: if (!strcmp(optarg, "open") || !strcmp(optarg, "standalone")) { s->fail_mode = OFPROTO_FAIL_STANDALONE; @@ -467,17 +453,11 @@ parse_options(int argc, char *argv[], struct ofsettings *s) argc -= optind; argv += optind; - if (argc < 1) { - ovs_fatal(0, "need at least one non-option arguments; " + if (argc < 2) { + ovs_fatal(0, "need at least two non-option arguments; " "use --help for usage"); } - /* Set accept_controller_regex. */ - if (!controller_opts.accept_re) { - controller_opts.accept_re - = stream_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*"; - } - /* Rate limiting. */ if (controller_opts.rate_limit && controller_opts.rate_limit < 100) { VLOG_WARN("Rate limit set to unusually low value %d", @@ -500,9 +480,6 @@ parse_options(int argc, char *argv[], struct ofsettings *s) svec_add(&controllers, argv[i]); } } - if (argc < 2) { - svec_add(&controllers, "discover"); - } /* Set up controllers. */ s->n_controllers = controllers.n; @@ -511,27 +488,16 @@ parse_options(int argc, char *argv[], struct ofsettings *s) s->controllers[i] = controller_opts; s->controllers[i].target = controllers.names[i]; } - - /* Sanity check. */ - if (controller_opts.band == OFPROTO_OUT_OF_BAND) { - for (i = 0; i < s->n_controllers; i++) { - if (!strcmp(s->controllers[i].target, "discover")) { - ovs_fatal(0, "Cannot perform discovery with out-of-band " - "control"); - } - } - } } static void usage(void) { printf("%s: an OpenFlow switch implementation.\n" - "usage: %s [OPTIONS] [TYPE@]DATAPATH [CONTROLLER...]\n" + "usage: %s [OPTIONS] [TYPE@]DATAPATH CONTROLLER...\n" "where DATAPATH is a local datapath (e.g. \"dp0\")\n" "optionally with an explicit TYPE (default: \"system\").\n" - "Each CONTROLLER is an active OpenFlow connection method. If\n" - "none is given, ovs-openflowd performs controller discovery.\n", + "Each CONTROLLER is an active OpenFlow connection method.\n", program_name, program_name); vconn_usage(true, true, true); printf("\nOpenFlow options:\n" @@ -542,9 +508,6 @@ usage(void) " --sw-desc=SW Identify software as SW\n" " --serial-desc=SERIAL Identify serial number as SERIAL\n" " --dp-desc=DP_DESC Identify dp description as DP_DESC\n" - "\nController discovery options:\n" - " --accept-vconn=REGEX accept matching discovered controllers\n" - " --no-resolv-conf do not update /etc/resolv.conf\n" "\nNetworking options:\n" " --fail=open|closed when controller connection fails:\n" " closed: drop all packets\n" diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 6f8ca25e..9fb25795 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1956,8 +1956,6 @@ bridge_ofproto_controller_for_mgmt(const struct bridge *br, oc->max_backoff = 0; oc->probe_interval = 60; oc->band = OFPROTO_OUT_OF_BAND; - oc->accept_re = NULL; - oc->update_resolv_conf = false; oc->rate_limit = 0; oc->burst_limit = 0; } @@ -1972,8 +1970,6 @@ bridge_ofproto_controller_from_ovsrec(const struct ovsrec_controller *c, oc->probe_interval = c->inactivity_probe ? *c->inactivity_probe / 1000 : 5; oc->band = (!c->connection_mode || !strcmp(c->connection_mode, "in-band") ? OFPROTO_IN_BAND : OFPROTO_OUT_OF_BAND); - oc->accept_re = c->discover_accept_regex; - oc->update_resolv_conf = c->discover_update_resolv_conf; oc->rate_limit = c->controller_rate_limit ? *c->controller_rate_limit : 0; oc->burst_limit = (c->controller_burst_limit ? *c->controller_burst_limit : 0); @@ -1991,11 +1987,6 @@ bridge_configure_local_iface_netdev(struct bridge *br, struct iface *local_iface; struct in_addr ip; - /* Controller discovery does its own TCP/IP configuration later. */ - if (strcmp(c->target, "discover")) { - return; - } - /* If there's no local interface or no IP address, give up. */ local_iface = bridge_get_local_iface(br); if (!local_iface || !c->local_ip || !inet_aton(c->local_ip, &ip)) { diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 7618e2d5..e808aa3d 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "2.1.0", - "cksum": "1990266641 15714", + "version": "3.0.0", + "cksum": "705848946 15525", "tables": { "Open_vSwitch": { "columns": { @@ -362,10 +362,6 @@ "min": 0, "max": 1}}, "inactivity_probe": { "type": {"key": "integer", "min": 0, "max": 1}}, - "discover_accept_regex": { - "type": {"key": "string", "min": 0, "max": 1}}, - "discover_update_resolv_conf": { - "type": {"key": "boolean", "min": 0, "max": 1}}, "connection_mode": { "type": {"key": {"type": "string", "enum": ["set", ["in-band", "out-of-band"]]}, diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 470f3897..ad1bffa3 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1692,23 +1692,6 @@
The specified TCP port (default: 6633) on the host at the given ip, which must be expressed as an IP address (not a DNS name).
-
discover
-
-

Enables controller discovery.

-

In controller discovery mode, Open vSwitch broadcasts a DHCP - request with vendor class identifier OpenFlow across - all of the bridge's network devices. It will accept any valid - DHCP reply that has the same vendor class identifier and includes - a vendor-specific option with code 1 whose contents are a string - specifying the location of the controller in the same format as - .

-

The DHCP reply may also, optionally, include a vendor-specific - option with code 2 whose contents are a string specifying the URI - to the base of the OpenFlow PKI - (e.g. http://192.168.0.1/openflow/pki). This URI is - used only for bootstrapping the OpenFlow PKI at initial switch - setup; ovs-vswitchd does not use it at all.

-

The following connection methods are currently supported for service @@ -1768,10 +1751,7 @@ -

If not specified, the default is implementation-specific. If - is discover, the connection mode - is always treated as in-band regardless of the actual - setting.

+

If not specified, the default is implementation-specific.

@@ -1821,33 +1801,9 @@ - -

These values are considered only when - is discover.

- - - A POSIX - extended regular expression against which the discovered controller - location is validated. The regular expression is implicitly - anchored at the beginning of the controller location string, as - if it begins with ^. If not specified, the default - is implementation-specific. - - - - Whether to update /etc/resolv.conf when the - controller is discovered. If not specified, the default - is implementation-specific. Open vSwitch will only modify - /etc/resolv.conf if the DHCP response that it receives - specifies one or more DNS servers. - -
-

These values are considered only in in-band control mode (see - ) and only when - is not discover. (For controller discovery, the network - configuration obtained via DHCP is used instead.)

+ ).

When multiple controllers are configured on a single bridge, there should be only one set of unique values in these columns. If different diff --git a/xenserver/openvswitch-xen.spec b/xenserver/openvswitch-xen.spec index 7f2cabd1..6516086f 100644 --- a/xenserver/openvswitch-xen.spec +++ b/xenserver/openvswitch-xen.spec @@ -116,11 +116,9 @@ install xenserver/uuid.py $RPM_BUILD_ROOT/usr/share/openvswitch/python # Get rid of stuff we don't want to make RPM happy. rm \ $RPM_BUILD_ROOT/usr/bin/ovs-controller \ - $RPM_BUILD_ROOT/usr/bin/ovs-discover \ $RPM_BUILD_ROOT/usr/bin/ovs-openflowd \ $RPM_BUILD_ROOT/usr/bin/ovs-pki \ $RPM_BUILD_ROOT/usr/share/man/man8/ovs-controller.8 \ - $RPM_BUILD_ROOT/usr/share/man/man8/ovs-discover.8 \ $RPM_BUILD_ROOT/usr/share/man/man8/ovs-openflowd.8 \ $RPM_BUILD_ROOT/usr/share/man/man8/ovs-pki.8 -- 2.30.2