* derivatives without specific, written prior permission.
*/
+#include <config.h>
#include <errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <netinet/in.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "openflow.h"
#include "ofp-print.h"
#include "random.h"
-#include "signal.h"
+#include "timeval.h"
#include "vconn.h"
#include "vconn-ssl.h"
#include "vlog.h"
#define THIS_MODULE VLM_dpctl
-#define DEFAULT_MAX_IDLE 60
+#define DEFAULT_IDLE_TIMEOUT 60
#define MAX_ADD_ACTS 5
static const char* ifconfigbin = "/sbin/ifconfig";
struct command *p;
set_program_name(argv[0]);
+ time_init();
vlog_init();
parse_options(argc, argv);
+ signal(SIGPIPE, SIG_IGN);
argc -= optind;
argv += optind;
for (;;) {
unsigned long int timeout;
- int indexptr;
int c;
- c = getopt_long(argc, argv, short_options, long_options, &indexptr);
+ c = getopt_long(argc, argv, short_options, long_options, NULL);
if (c == -1) {
break;
}
if (timeout <= 0) {
fatal(0, "value %s on -t or --timeout is not at least 1",
optarg);
- } else if (timeout < UINT_MAX) {
- /* Add 1 because historical implementations allow an alarm to
- * occur up to a second early. */
- alarm(timeout + 1);
} else {
- alarm(UINT_MAX);
+ time_alarm(timeout);
}
- signal(SIGALRM, SIG_DFL);
break;
case 'h':
vconn_usage(true, false);
printf("\nOptions:\n"
" -t, --timeout=SECS give up after SECS seconds\n"
- " -v, --verbose=MODULE:FACILITY:LEVEL configure logging levels\n"
+ " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n"
" -v, --verbose set maximum verbosity level\n"
" -h, --help display this help message\n"
" -V, --version display version information\n");
run(vconn_send_block(vconn, buffer), "failed to send packet to switch");
}
-static struct buffer *
-transact_openflow(struct vconn *vconn, struct buffer *request)
-{
- uint32_t send_xid = ((struct ofp_header *) request->data)->xid;
-
- send_openflow_buffer(vconn, request);
- for (;;) {
- uint32_t recv_xid;
- struct buffer *reply;
-
- run(vconn_recv_block(vconn, &reply), "OpenFlow packet receive failed");
- recv_xid = ((struct ofp_header *) reply->data)->xid;
- if (send_xid == recv_xid) {
- return reply;
- }
-
- VLOG_DBG("received reply with xid %08"PRIx32" != expected %08"PRIx32,
- recv_xid, send_xid);
- buffer_delete(reply);
- }
-}
-
static void
dump_transaction(const char *vconn_name, struct buffer *request)
{
update_openflow_length(request);
run(vconn_open_block(vconn_name, &vconn), "connecting to %s", vconn_name);
- reply = transact_openflow(vconn, request);
+ run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name);
ofp_print(stdout, reply->data, reply->size, 1);
vconn_close(vconn);
}
static void
str_to_flow(char *string, struct ofp_match *match,
struct ofp_action *action, int *n_actions, uint8_t *table_idx,
- uint16_t *priority, uint16_t *max_idle)
+ uint16_t *priority, uint16_t *idle_timeout, uint16_t *hard_timeout)
{
struct field {
const char *name;
if (priority) {
*priority = OFP_DEFAULT_PRIORITY;
}
- if (max_idle) {
- *max_idle = DEFAULT_MAX_IDLE;
+ if (idle_timeout) {
+ *idle_timeout = DEFAULT_IDLE_TIMEOUT;
+ }
+ if (hard_timeout) {
+ *hard_timeout = OFP_FLOW_PERMANENT;
}
if (action) {
act_str = strstr(string, "action");
continue;
}
- if (max_idle && !strcmp(name, "max_idle")) {
- *max_idle = atoi(value);
+ if (idle_timeout && !strcmp(name, "idle_timeout")) {
+ *idle_timeout = atoi(value);
+ continue;
+ }
+
+ if (hard_timeout && !strcmp(name, "hard_timeout")) {
+ *hard_timeout = atoi(value);
continue;
}
req = alloc_stats_request(sizeof *req, OFPST_FLOW, &request);
str_to_flow(argc > 2 ? argv[2] : "", &req->match, NULL, 0,
- &req->table_id, NULL, NULL);
+ &req->table_id, NULL, NULL, NULL);
memset(req->pad, 0, sizeof req->pad);
dump_stats_transaction(argv[1], request);
req = alloc_stats_request(sizeof *req, OFPST_AGGREGATE, &request);
str_to_flow(argc > 2 ? argv[2] : "", &req->match, NULL, 0,
- &req->table_id, NULL, NULL);
+ &req->table_id, NULL, NULL, NULL);
memset(req->pad, 0, sizeof req->pad);
dump_stats_transaction(argv[1], request);
struct vconn *vconn;
struct buffer *buffer;
struct ofp_flow_mod *ofm;
- uint16_t priority, max_idle;
+ uint16_t priority, idle_timeout, hard_timeout;
size_t size;
int n_actions = MAX_ADD_ACTS;
size = sizeof *ofm + (sizeof ofm->actions[0] * MAX_ADD_ACTS);
ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer);
str_to_flow(argv[2], &ofm->match, &ofm->actions[0], &n_actions,
- NULL, &priority, &max_idle);
+ NULL, &priority, &idle_timeout, &hard_timeout);
ofm->command = htons(OFPFC_ADD);
- ofm->max_idle = htons(max_idle);
+ 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);
while (fgets(line, sizeof line, file)) {
struct buffer *buffer;
struct ofp_flow_mod *ofm;
- uint16_t priority, max_idle;
+ uint16_t priority, idle_timeout, hard_timeout;
size_t size;
int n_actions = MAX_ADD_ACTS;
size = sizeof *ofm + (sizeof ofm->actions[0] * MAX_ADD_ACTS);
ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer);
str_to_flow(line, &ofm->match, &ofm->actions[0], &n_actions,
- NULL, &priority, &max_idle);
+ NULL, &priority, &idle_timeout, &hard_timeout);
ofm->command = htons(OFPFC_ADD);
- ofm->max_idle = htons(max_idle);
+ 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);
size = sizeof *ofm;
ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer);
str_to_flow(argc > 2 ? argv[2] : "", &ofm->match, NULL, 0, NULL,
- &priority, NULL);
+ &priority, NULL, NULL);
ofm->command = htons(OFPFC_DELETE);
- ofm->max_idle = htons(0);
+ ofm->idle_timeout = htons(0);
+ ofm->hard_timeout = htons(0);
ofm->buffer_id = htonl(UINT32_MAX);
ofm->priority = htons(priority);
ofm->reserved = htonl(0);
make_openflow(sizeof(struct ofp_header), OFPT_ECHO_REQUEST, &request);
run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
- reply = transact_openflow(vconn, request);
+ run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]);
if (reply->size != request->size) {
fatal(0, "reply does not match request");
}
random_bytes(rq_hdr + 1, payload);
gettimeofday(&start, NULL);
- reply = transact_openflow(vconn, buffer_clone(request));
+ run(vconn_transact(vconn, buffer_clone(request), &reply), "transact");
gettimeofday(&end, NULL);
rpy_hdr = reply->data;
run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
gettimeofday(&start, NULL);
for (i = 0; i < count; i++) {
- struct buffer *request;
+ struct buffer *request, *reply;
struct ofp_header *rq_hdr;
rq_hdr = make_openflow(message_size, OFPT_ECHO_REQUEST, &request);
memset(rq_hdr + 1, 0, payload_size);
- buffer_delete(transact_openflow(vconn, request));
+ run(vconn_transact(vconn, request, &reply), "transact");
+ buffer_delete(reply);
}
gettimeofday(&end, NULL);
vconn_close(vconn);