/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * 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.
#include "util.h"
#include "vconn-ssl.h"
#include "vconn.h"
+#include "xtoxll.h"
#include "vlog.h"
#define THIS_MODULE VLM_ofctl
parse_options(int argc, char *argv[], struct settings *s)
{
enum {
- OPT_STRICT = UCHAR_MAX + 1
+ OPT_STRICT = UCHAR_MAX + 1,
+ VLOG_OPTION_ENUMS
};
static struct option long_options[] = {
{"timeout", required_argument, 0, 't'},
- {"verbose", optional_argument, 0, 'v'},
{"strict", no_argument, 0, OPT_STRICT},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
+ VLOG_LONG_OPTIONS,
VCONN_SSL_LONG_OPTIONS
{0, 0, 0, 0},
};
OVS_PRINT_VERSION(OFP_VERSION, OFP_VERSION);
exit(EXIT_SUCCESS);
- case 'v':
- vlog_set_verbosity(optarg);
- break;
-
case OPT_STRICT:
s->strict = true;
break;
+ VLOG_OPTION_HANDLERS
VCONN_SSL_OPTION_HANDLERS
case '?':
static void
open_vconn(const char *name, struct vconn **vconnp)
{
- struct dpif dpif;
+ struct dpif *dpif;
struct stat s;
if (strstr(name, ":")) {
char *socket_name;
char *vconn_name;
- run(dpif_get_name(&dpif, dpif_name, sizeof dpif_name),
+ run(dpif_port_get_name(dpif, ODPP_LOCAL, dpif_name, sizeof dpif_name),
"obtaining name of %s", dpif_name);
- dpif_close(&dpif);
+ dpif_close(dpif);
if (strcmp(dpif_name, name)) {
VLOG_INFO("datapath %s is named %s", name, dpif_name);
}
static void
str_to_mac(const char *str, uint8_t mac[6])
{
- if (sscanf(str, "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8,
- &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 6) {
+ if (sscanf(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
+ != ETH_ADDR_SCAN_COUNT) {
ovs_fatal(0, "invalid mac address %s", str);
}
}
put_dl_addr_action(b, OFPAT_SET_DL_SRC, arg);
} else if (!strcasecmp(act, "mod_dl_dst")) {
put_dl_addr_action(b, OFPAT_SET_DL_DST, arg);
+ } else if (!strcasecmp(act, "mod_nw_src")) {
+ struct ofp_action_nw_addr *na;
+ na = put_action(b, sizeof *na, OFPAT_SET_NW_SRC);
+ str_to_ip(arg, &na->nw_addr);
+ } else if (!strcasecmp(act, "mod_nw_dst")) {
+ struct ofp_action_nw_addr *na;
+ na = put_action(b, sizeof *na, OFPAT_SET_NW_DST);
+ str_to_ip(arg, &na->nw_addr);
+ } else if (!strcasecmp(act, "mod_tp_src")) {
+ struct ofp_action_tp_port *ta;
+ ta = put_action(b, sizeof *ta, OFPAT_SET_TP_SRC);
+ ta->tp_port = htons(str_to_u32(arg));
+ } else if (!strcasecmp(act, "mod_tp_dst")) {
+ struct ofp_action_tp_port *ta;
+ ta = put_action(b, sizeof *ta, OFPAT_SET_TP_DST);
+ ta->tp_port = htons(str_to_u32(arg));
+ } else if (!strcasecmp(act, "mod_nw_tos")) {
+ struct ofp_action_nw_tos *nt;
+ nt = put_action(b, sizeof *nt, OFPAT_SET_NW_TOS);
+ nt->nw_tos = str_to_u32(arg);
} else if (!strcasecmp(act, "output")) {
put_output_action(b, str_to_u32(arg));
} else if (!strcasecmp(act, "drop")) {
* packet to the controller. */
if (arg && (strspn(act, "0123456789") == strlen(act))) {
oao->max_len = htons(str_to_u32(arg));
+ } else {
+ oao->max_len = htons(UINT16_MAX);
}
} else if (parse_port_name(act, &port)) {
put_output_action(b, port);
static const struct field fields[] = {
{ "in_port", OFPFW_IN_PORT, F_U16, F_OFS(in_port), 0 },
{ "dl_vlan", OFPFW_DL_VLAN, F_U16, F_OFS(dl_vlan), 0 },
+ { "dl_vlan_pcp", OFPFW_DL_VLAN_PCP, F_U8, F_OFS(dl_vlan_pcp), 0 },
{ "dl_src", OFPFW_DL_SRC, F_MAC, F_OFS(dl_src), 0 },
{ "dl_dst", OFPFW_DL_DST, F_MAC, F_OFS(dl_dst), 0 },
{ "dl_type", OFPFW_DL_TYPE, F_U16, F_OFS(dl_type), 0 },
{ "nw_dst", OFPFW_NW_DST_MASK, F_IP,
F_OFS(nw_dst), OFPFW_NW_DST_SHIFT },
{ "nw_proto", OFPFW_NW_PROTO, F_U8, F_OFS(nw_proto), 0 },
+ { "nw_tos", OFPFW_NW_TOS, F_U8, F_OFS(nw_tos), 0 },
{ "tp_src", OFPFW_TP_SRC, F_U16, F_OFS(tp_src), 0 },
{ "tp_dst", OFPFW_TP_DST, F_U16, F_OFS(tp_dst), 0 },
{ "icmp_type", OFPFW_ICMP_TYPE, F_U16, F_OFS(icmp_type), 0 },
static void
str_to_flow(char *string, struct ofp_match *match, struct ofpbuf *actions,
uint8_t *table_idx, uint16_t *out_port, uint16_t *priority,
- uint16_t *idle_timeout, uint16_t *hard_timeout)
+ uint16_t *idle_timeout, uint16_t *hard_timeout,
+ uint64_t *cookie)
{
char *save_ptr = NULL;
char *name;
if (hard_timeout) {
*hard_timeout = OFP_FLOW_PERMANENT;
}
+ if (cookie) {
+ *cookie = 0;
+ }
if (actions) {
char *act_str = strstr(string, "action");
if (!act_str) {
*idle_timeout = atoi(value);
} else if (hard_timeout && !strcmp(name, "hard_timeout")) {
*hard_timeout = atoi(value);
+ } else if (cookie && !strcmp(name, "cookie")) {
+ *cookie = atoi(value);
} else if (parse_field(name, &f)) {
void *data = (char *) match + f->offset;
if (!strcmp(value, "*") || !strcmp(value, "ANY")) {
req = alloc_stats_request(sizeof *req, OFPST_FLOW, &request);
str_to_flow(argc > 2 ? argv[2] : "", &req->match, NULL,
- &req->table_id, &out_port, NULL, NULL, NULL);
+ &req->table_id, &out_port, NULL, NULL, NULL, NULL);
memset(&req->pad, 0, sizeof req->pad);
req->out_port = htons(out_port);
req = alloc_stats_request(sizeof *req, OFPST_AGGREGATE, &request);
str_to_flow(argc > 2 ? argv[2] : "", &req->match, NULL,
- &req->table_id, &out_port, NULL, NULL, NULL);
+ &req->table_id, &out_port, NULL, NULL, NULL, NULL);
memset(&req->pad, 0, sizeof req->pad);
req->out_port = htons(out_port);
struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
uint16_t priority, idle_timeout, hard_timeout;
+ uint64_t cookie;
struct ofp_match match;
/* Parse and send. str_to_flow() will expand and reallocate the data in
* 'buffer', so we can't keep pointers to across the str_to_flow() call. */
make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
str_to_flow(argv[2], &match, buffer,
- NULL, NULL, &priority, &idle_timeout, &hard_timeout);
+ NULL, NULL, &priority, &idle_timeout, &hard_timeout,
+ &cookie);
ofm = buffer->data;
ofm->match = match;
ofm->command = htons(OFPFC_ADD);
+ ofm->cookie = htonll(cookie);
ofm->idle_timeout = htons(idle_timeout);
ofm->hard_timeout = htons(hard_timeout);
ofm->buffer_id = htonl(UINT32_MAX);
ofm->priority = htons(priority);
- ofm->reserved = htonl(0);
open_vconn(argv[1], &vconn);
send_openflow_buffer(vconn, buffer);
struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
uint16_t priority, idle_timeout, hard_timeout;
+ uint64_t cookie;
struct ofp_match match;
char *comment;
* call. */
ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
str_to_flow(line, &match, buffer,
- NULL, NULL, &priority, &idle_timeout, &hard_timeout);
+ NULL, NULL, &priority, &idle_timeout, &hard_timeout,
+ &cookie);
ofm = buffer->data;
ofm->match = match;
ofm->command = htons(OFPFC_ADD);
+ ofm->cookie = htonll(cookie);
ofm->idle_timeout = htons(idle_timeout);
ofm->hard_timeout = htons(hard_timeout);
ofm->buffer_id = htonl(UINT32_MAX);
ofm->priority = htons(priority);
- ofm->reserved = htonl(0);
send_openflow_buffer(vconn, buffer);
}
do_mod_flows(const struct settings *s, int argc UNUSED, char *argv[])
{
uint16_t priority, idle_timeout, hard_timeout;
+ uint64_t cookie;
struct vconn *vconn;
struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
+ struct ofp_match match;
- /* Parse and send. */
- ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- str_to_flow(argv[2], &ofm->match, buffer,
- NULL, NULL, &priority, &idle_timeout, &hard_timeout);
+ /* Parse and send. str_to_flow() will expand and reallocate the data in
+ * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
+ make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
+ str_to_flow(argv[2], &match, buffer,
+ NULL, NULL, &priority, &idle_timeout, &hard_timeout,
+ &cookie);
+ ofm = buffer->data;
+ ofm->match = match;
if (s->strict) {
ofm->command = htons(OFPFC_MODIFY_STRICT);
} else {
}
ofm->idle_timeout = htons(idle_timeout);
ofm->hard_timeout = htons(hard_timeout);
+ ofm->cookie = htonll(cookie);
ofm->buffer_id = htonl(UINT32_MAX);
ofm->priority = htons(priority);
- ofm->reserved = htonl(0);
open_vconn(argv[1], &vconn);
send_openflow_buffer(vconn, buffer);
/* Parse and send. */
ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
str_to_flow(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL,
- &out_port, &priority, NULL, NULL);
+ &out_port, &priority, NULL, NULL, NULL);
if (s->strict) {
ofm->command = htons(OFPFC_DELETE_STRICT);
} else {
ofm->buffer_id = htonl(UINT32_MAX);
ofm->out_port = htons(out_port);
ofm->priority = htons(priority);
- ofm->reserved = htonl(0);
open_vconn(argv[1], &vconn);
send_openflow_buffer(vconn, buffer);
open_vconn(argv[1], &vconn);
if (argc > 2) {
int miss_send_len = atoi(argv[2]);
- int send_flow_exp = argc > 3 ? atoi(argv[3]) : 0;
struct ofp_switch_config *osc;
struct ofpbuf *buf;
osc = make_openflow(sizeof *osc, OFPT_SET_CONFIG, &buf);
- osc->flags = htons(send_flow_exp ? OFPC_SEND_FLOW_EXP : 0);
osc->miss_send_len = htons(miss_send_len);
send_openflow_buffer(vconn, buf);
}
printf("Reply:\n");
ofp_print(stdout, reply, reply->size, 2);
}
- printf("%d bytes from %s: xid=%08"PRIx32" time=%.1f ms\n",
+ printf("%zu bytes from %s: xid=%08"PRIx32" time=%.1f ms\n",
reply->size - sizeof *rpy_hdr, argv[1], rpy_hdr->xid,
(1000*(double)(end.tv_sec - start.tv_sec))
+ (.001*(end.tv_usec - start.tv_usec)));