/*
* Copyright (c) 2008, 2009 Nicira Networks.
*
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * 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:
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * 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 <config.h>
printf("\n");
if (active) {
printf("Active OpenFlow connection methods:\n");
- printf(" tcp:HOST[:PORT] "
- "PORT (default: %d) on remote TCP HOST\n", OFP_TCP_PORT);
+ printf(" tcp:IP[:PORT] "
+ "PORT (default: %d) at remote IP\n", OFP_TCP_PORT);
#ifdef HAVE_OPENSSL
- printf(" ssl:HOST[:PORT] "
- "SSL PORT (default: %d) on remote HOST\n", OFP_SSL_PORT);
+ printf(" ssl:IP[:PORT] "
+ "SSL PORT (default: %d) at remote IP\n", OFP_SSL_PORT);
#endif
printf(" unix:FILE Unix domain socket named FILE\n");
}
/* Returns the IP address of the peer, or 0 if the peer is not connected over
* an IP-based protocol or if its IP address is not yet known. */
uint32_t
-vconn_get_ip(const struct vconn *vconn)
+vconn_get_remote_ip(const struct vconn *vconn)
{
- return vconn->ip;
+ return vconn->remote_ip;
+}
+
+/* Returns the transport port of the peer, or 0 if the connection does not
+ * contain a port or if the port is not yet known. */
+uint16_t
+vconn_get_remote_port(const struct vconn *vconn)
+{
+ return vconn->remote_port;
+}
+
+/* Returns the IP address used to connect to the peer, or 0 if the
+ * connection is not an IP-based protocol or if its IP address is not
+ * yet known. */
+uint32_t
+vconn_get_local_ip(const struct vconn *vconn)
+{
+ return vconn->local_ip;
+}
+
+/* Returns the transport port used to connect to the peer, or 0 if the
+ * connection does not contain a port or if the port is not yet known. */
+uint16_t
+vconn_get_local_port(const struct vconn *vconn)
+{
+ return vconn->local_port;
}
static void
memcpy(ofm->match.dl_src, flow->dl_src, sizeof ofm->match.dl_src);
memcpy(ofm->match.dl_dst, flow->dl_dst, sizeof ofm->match.dl_dst);
ofm->match.dl_vlan = flow->dl_vlan;
+ ofm->match.dl_vlan_pcp = flow->dl_vlan_pcp;
ofm->match.dl_type = flow->dl_type;
ofm->match.nw_src = flow->nw_src;
ofm->match.nw_dst = flow->nw_dst;
return buffer;
}
+struct ofpbuf *
+make_packet_in(uint32_t buffer_id, uint16_t in_port, uint8_t reason,
+ const struct ofpbuf *payload, int max_send_len)
+{
+ struct ofp_packet_in *opi;
+ struct ofpbuf *buf;
+ int send_len;
+
+ send_len = MIN(max_send_len, payload->size);
+ buf = ofpbuf_new(sizeof *opi + send_len);
+ opi = put_openflow_xid(offsetof(struct ofp_packet_in, data),
+ OFPT_PACKET_IN, 0, buf);
+ opi->buffer_id = htonl(buffer_id);
+ opi->total_len = htons(payload->size);
+ opi->in_port = htons(in_port);
+ opi->reason = reason;
+ ofpbuf_put(buf, payload->data, send_len);
+ update_openflow_length(buf);
+
+ return buf;
+}
+
struct ofpbuf *
make_packet_out(const struct ofpbuf *packet, uint32_t buffer_id,
uint16_t in_port,
if (got_size != size) {
char *type_name = ofp_message_type_to_string(type);
VLOG_WARN_RL(&bad_ofmsg_rl,
- "received %s message of length %"PRIu16" (expected %zu)",
+ "received %s message of length %zu (expected %zu)",
type_name, got_size, size);
free(type_name);
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+ return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
}
return 0;
got_size = ntohs(msg->length);
if (got_size < min_size) {
char *type_name = ofp_message_type_to_string(type);
- VLOG_WARN_RL(&bad_ofmsg_rl, "received %s message of length %"PRIu16" "
+ VLOG_WARN_RL(&bad_ofmsg_rl, "received %s message of length %zu "
"(expected at least %zu)",
type_name, got_size, min_size);
free(type_name);
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+ return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
}
if ((got_size - min_size) % array_elt_size) {
char *type_name = ofp_message_type_to_string(type);
VLOG_WARN_RL(&bad_ofmsg_rl,
- "received %s message of bad length %"PRIu16": the "
+ "received %s message of bad length %zu: the "
"excess over %zu (%zu) is not evenly divisible by %zu "
"(remainder is %zu)",
type_name, got_size, min_size, got_size - min_size,
array_elt_size, (got_size - min_size) % array_elt_size);
free(type_name);
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+ return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
}
if (n_array_elts) {
*n_array_elts = (got_size - min_size) / array_elt_size;
actions_len = ntohs(opo->actions_len);
if (actions_len > extra) {
- VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %zu bytes of actions "
+ VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %u bytes of actions "
"but message has room for only %zu bytes",
actions_len, extra);
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+ return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
}
if (actions_len % sizeof(union ofp_action)) {
- VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %zu bytes of actions, "
+ VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %u bytes of actions, "
"which is not a multiple of %zu",
actions_len, sizeof(union ofp_action));
- return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+ return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
}
n_actions = actions_len / sizeof(union ofp_action);
{
int error;
- switch (a->type) {
+ switch (ntohs(a->type)) {
case OFPAT_OUTPUT:
error = check_action_port(ntohs(a->output.port), max_ports);
if (error) {
case OFPAT_STRIP_VLAN:
case OFPAT_SET_NW_SRC:
case OFPAT_SET_NW_DST:
+ case OFPAT_SET_NW_TOS:
case OFPAT_SET_TP_SRC:
case OFPAT_SET_TP_DST:
return check_action_exact_len(a, len, 8);
break;
default:
- VLOG_WARN_RL(&bad_ofmsg_rl, "unknown action type %"PRIu16, a->type);
+ VLOG_WARN_RL(&bad_ofmsg_rl, "unknown action type %"PRIu16,
+ ntohs(a->type));
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE);
}
if (n_slots > slots_left) {
VLOG_DBG_RL(&bad_ofmsg_rl,
- "action requires %u slots but only %td remain",
+ "action requires %u slots but only %u remain",
n_slots, slots_left);
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
}
if (wc & OFPFW_DL_TYPE) {
m->dl_type = 0;
- /* Can't sensibly m on network or transport headers if the
+ /* Can't sensibly match on network or transport headers if the
* data link type is unknown. */
wc |= OFPFW_NW | OFPFW_TP;
m->nw_src = m->nw_dst = m->nw_proto = 0;
if (wc & OFPFW_NW_PROTO) {
m->nw_proto = 0;
- /* Can't sensibly m on transport headers if the network
+ /* Can't sensibly match on transport headers if the network
* protocol is unknown. */
wc |= OFPFW_TP;
m->tp_src = m->tp_dst = 0;
}
} else {
/* Transport layer fields will always be extracted as zeros, so we
- * can do an exact-m on those values. */
+ * can do an exact-match on those values. */
wc &= ~OFPFW_TP;
m->tp_src = m->tp_dst = 0;
}
}
} else {
/* Network and transport layer fields will always be extracted as
- * zeros, so we can do an exact-m on those values. */
+ * zeros, so we can do an exact-match on those values. */
wc &= ~(OFPFW_NW | OFPFW_TP);
m->nw_proto = m->nw_src = m->nw_dst = 0;
m->tp_src = m->tp_dst = 0;
m->wildcards = htonl(wc);
}
+/* Initializes 'vconn' as a new vconn named 'name', implemented via 'class'.
+ * The initial connection status, supplied as 'connect_status', is interpreted
+ * as follows:
+ *
+ * - 0: 'vconn' is connected. Its 'send' and 'recv' functions may be
+ * called in the normal fashion.
+ *
+ * - EAGAIN: 'vconn' is trying to complete a connection. Its 'connect'
+ * function should be called to complete the connection.
+ *
+ * - Other positive errno values indicate that the connection failed with
+ * the specified error.
+ *
+ * After calling this function, vconn_close() must be used to destroy 'vconn',
+ * otherwise resources will be leaked.
+ *
+ * The caller retains ownership of 'name'. */
void
vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
- uint32_t ip, const char *name, bool reconnectable)
+ const char *name)
{
vconn->class = class;
vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING
vconn->error = connect_status;
vconn->version = -1;
vconn->min_version = -1;
- vconn->ip = ip;
+ vconn->remote_ip = 0;
+ vconn->remote_port = 0;
+ vconn->local_ip = 0;
+ vconn->local_port = 0;
vconn->name = xstrdup(name);
- vconn->reconnectable = reconnectable;
+}
+
+void
+vconn_set_remote_ip(struct vconn *vconn, uint32_t ip)
+{
+ vconn->remote_ip = ip;
+}
+
+void
+vconn_set_remote_port(struct vconn *vconn, uint16_t port)
+{
+ vconn->remote_port = port;
+}
+
+void
+vconn_set_local_ip(struct vconn *vconn, uint32_t ip)
+{
+ vconn->local_ip = ip;
+}
+
+void
+vconn_set_local_port(struct vconn *vconn, uint16_t port)
+{
+ vconn->local_port = port;
}
void