From aaaa7553a9b7fef47436e96fb0177981b09e4a83 Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Wed, 28 Jul 2010 15:18:14 -0700 Subject: [PATCH] learning-switch: Add ability to define default flows Add an argument to the function to create a learning switch, which defines default flows to be pushed down to connecting switches. It does nothing to enforce that they remain intact. It only pushes flows on switch connection. --- lib/learning-switch.c | 62 +++++++++++++++++++++++++++++++++++++- lib/learning-switch.h | 5 +-- utilities/ovs-controller.c | 2 +- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/lib/learning-switch.c b/lib/learning-switch.c index d2da2523..22fa70d5 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -26,6 +26,7 @@ #include "flow.h" #include "mac-learning.h" #include "ofpbuf.h" +#include "ofp-parse.h" #include "ofp-print.h" #include "ofp-util.h" #include "openflow/openflow.h" @@ -84,6 +85,8 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); static void queue_tx(struct lswitch *, struct rconn *, struct ofpbuf *); static void send_features_request(struct lswitch *, struct rconn *); +static void send_default_flows(struct lswitch *sw, struct rconn *rconn, + FILE *default_flows); static void schedule_query(struct lswitch *, long long int delay); static bool may_learn(const struct lswitch *, uint16_t port_no); static bool may_recv(const struct lswitch *, uint16_t port_no, @@ -107,10 +110,17 @@ static packet_handler_func process_stats_reply; * after the given number of seconds (or never expire, if 'max_idle' is * OFP_FLOW_PERMANENT). Otherwise, the new switch will process every packet. * + * The caller may provide the file stream 'default_flows' that defines + * default flows that should be pushed when a switch connects. Each + * line is a flow entry in the format described for "add-flows" command + * in the Flow Syntax section of the ovs-ofct(8) man page. The caller + * is responsible for closing the stream. + * * 'rconn' is used to send out an OpenFlow features request. */ struct lswitch * lswitch_create(struct rconn *rconn, bool learn_macs, - bool exact_flows, int max_idle, bool action_normal) + bool exact_flows, int max_idle, bool action_normal, + FILE *default_flows) { struct lswitch *sw; size_t i; @@ -140,6 +150,9 @@ lswitch_create(struct rconn *rconn, bool learn_macs, sw->port_states[i] = P_DISABLED; } send_features_request(sw, rconn); + if (default_flows) { + send_default_flows(sw, rconn, default_flows); + } return sw; } @@ -359,6 +372,53 @@ send_features_request(struct lswitch *sw, struct rconn *rconn) } } +static void +send_default_flows(struct lswitch *sw, struct rconn *rconn, + FILE *default_flows) +{ + char line[1024]; + + while (fgets(line, sizeof line, default_flows)) { + struct ofpbuf *b; + struct ofp_flow_mod *ofm; + uint16_t priority, idle_timeout, hard_timeout; + uint64_t cookie; + struct ofp_match match; + + char *comment; + + /* Delete comments. */ + comment = strchr(line, '#'); + if (comment) { + *comment = '\0'; + } + + /* Drop empty lines. */ + if (line[strspn(line, " \t\n")] == '\0') { + continue; + } + + /* 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, &b); + parse_ofp_str(line, &match, b, + NULL, NULL, &priority, &idle_timeout, &hard_timeout, + &cookie); + ofm = b->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); + + update_openflow_length(b); + queue_tx(sw, rconn, b); + } +} + static void queue_tx(struct lswitch *sw, struct rconn *rconn, struct ofpbuf *b) { diff --git a/lib/learning-switch.h b/lib/learning-switch.h index a2ac53b9..3b414a5b 100644 --- a/lib/learning-switch.h +++ b/lib/learning-switch.h @@ -19,13 +19,14 @@ #include #include +#include struct ofpbuf; struct rconn; struct lswitch *lswitch_create(struct rconn *, bool learn_macs, - bool exact_flows, int max_idle, - bool action_normal); + bool exact_flows, int max_idle, + bool action_normal, FILE *default_flows); void lswitch_set_queue(struct lswitch *sw, uint32_t queue); void lswitch_run(struct lswitch *, struct rconn *); void lswitch_wait(struct lswitch *); diff --git a/utilities/ovs-controller.c b/utilities/ovs-controller.c index 92b84ae1..bacb0b39 100644 --- a/utilities/ovs-controller.c +++ b/utilities/ovs-controller.c @@ -215,7 +215,7 @@ new_switch(struct switch_ *sw, struct vconn *vconn) rconn_connect_unreliably(sw->rconn, vconn, NULL); sw->lswitch = lswitch_create(sw->rconn, learn_macs, exact_flows, set_up_flows ? max_idle : -1, - action_normal); + action_normal, NULL); lswitch_set_queue(sw->lswitch, queue_id); } -- 2.30.2