* fail-open mode. */
static int max_idle = 15;
+/* --max-backoff: Maximum interval between controller connection attempts, in
+ * seconds. */
+static int max_backoff = 15;
+
static void parse_options(int argc, char *argv[]);
static void usage(void) NO_RETURN;
int
main(int argc, char *argv[])
{
+ struct rconn *local_rconn, *remote_rconn;
struct vconn *listen_vconn;
struct relay *controller_relay;
const char *nl_name;
daemonize();
- controller_relay = relay_create(rconn_new(argv[optind], 1, 0),
- rconn_new(argv[optind + 1], 1,
- probe_interval),
- false);
+ local_rconn = rconn_create(1, 0, max_backoff);
+ retval = rconn_connect(local_rconn, nl_name);
+ if (retval == EAFNOSUPPORT) {
+ fatal(0, "No support for %s vconn", nl_name);
+ }
+
+ remote_rconn = rconn_create(1, probe_interval, max_backoff);
+ retval = rconn_connect(remote_rconn, argv[optind + 1]);
+ if (retval == EAFNOSUPPORT) {
+ fatal(0, "No support for %s vconn", argv[optind + 1]);
+ }
+ controller_relay = relay_create(local_rconn, remote_rconn, false);
for (;;) {
struct relay *r, *n;
free(r);
}
+static void
+queue_tx(struct rconn *rc, struct buffer *b)
+{
+ if (rconn_force_send(rc, b)) {
+ buffer_delete(b);
+ }
+}
+
static bool
is_controller_mac(const uint8_t dl_addr[ETH_ADDR_LEN],
struct rconn *controller)
struct ofp_packet_in *opi;
struct ofp_header *oh;
size_t pkt_ofs, pkt_len;
- struct buffer pkt, *b;
+ struct buffer pkt;
struct flow flow;
uint16_t in_port, out_port;
return false;
}
- /* Add new flow. */
if (out_port != OFPP_FLOOD) {
- b = make_add_simple_flow(&flow, ntohl(opi->buffer_id), out_port,
- max_idle);
- if (rconn_force_send(rc, b)) {
- buffer_delete(b);
- }
- }
+ /* The output port is known, so add a new flow. */
+ queue_tx(rc, make_add_simple_flow(&flow, ntohl(opi->buffer_id),
+ out_port, max_idle));
- /* If the switch didn't buffer the packet, we need to send a copy. */
- if (out_port == OFPP_FLOOD || ntohl(opi->buffer_id) == UINT32_MAX) {
- b = make_unbuffered_packet_out(&pkt, in_port, out_port);
- if (rconn_force_send(rc, b)) {
- buffer_delete(b);
+ /* If the switch didn't buffer the packet, we need to send a copy. */
+ if (ntohl(opi->buffer_id) == UINT32_MAX) {
+ queue_tx(rc, make_unbuffered_packet_out(&pkt, in_port, out_port));
+ }
+ } else {
+ /* We don't know that MAC. Send along the packet without setting up a
+ * flow. */
+ struct buffer *b;
+ if (ntohl(opi->buffer_id) == UINT32_MAX) {
+ b = make_unbuffered_packet_out(&pkt, in_port, out_port);
+ } else {
+ b = make_buffered_packet_out(ntohl(opi->buffer_id),
+ in_port, out_port);
}
+ queue_tx(rc, b);
}
return true;
}
static void
parse_options(int argc, char *argv[])
{
- enum { OPT_INACTIVITY_PROBE = UCHAR_MAX + 1, OPT_MAX_IDLE };
+ enum {
+ OPT_INACTIVITY_PROBE = UCHAR_MAX + 1,
+ OPT_MAX_IDLE,
+ OPT_MAX_BACKOFF
+ };
static struct option long_options[] = {
{"fail", required_argument, 0, 'f'},
{"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE},
{"max-idle", required_argument, 0, OPT_MAX_IDLE},
+ {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF},
{"listen", required_argument, 0, 'l'},
{"detach", no_argument, 0, 'D'},
{"pidfile", optional_argument, 0, 'P'},
}
break;
+ case OPT_MAX_BACKOFF:
+ max_backoff = atoi(optarg);
+ if (max_backoff < 1) {
+ fatal(0, "--max-backoff argument must be at least 1");
+ } else if (max_backoff > 3600) {
+ max_backoff = 3600;
+ }
+ break;
+
case 'D':
set_detach();
break;
" open (default): act as learning switch\n"
" --inactivity-probe=SECS time between inactivity probes\n"
" --max-idle=SECS max idle for flows set up by secchan\n"
+ " --max-backoff=SECS max time between controller connection\n"
+ " attempts (default: 15 seconds)\n"
" -l, --listen=METHOD allow management connections on METHOD\n"
" (a passive OpenFlow connection method)\n"
"\nOther options:\n"
" -D, --detach run in background as daemon\n"
" -P, --pidfile[=FILE] create pidfile (default: %s/secchan.pid)\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",