ofctrl: Fix use of uninitialized hash value in ofctrl_add_flow().
[cascardo/ovs.git] / ovn / controller / ofctrl.c
1 /* Copyright (c) 2015 Nicira, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17 #include "ofctrl.h"
18 #include "dirs.h"
19 #include "dynamic-string.h"
20 #include "hmap.h"
21 #include "match.h"
22 #include "ofp-actions.h"
23 #include "ofp-msgs.h"
24 #include "ofp-print.h"
25 #include "ofp-util.h"
26 #include "ofpbuf.h"
27 #include "openflow/openflow.h"
28 #include "openvswitch/vlog.h"
29 #include "ovn-controller.h"
30 #include "vswitch-idl.h"
31 #include "rconn.h"
32 #include "socket-util.h"
33
34 VLOG_DEFINE_THIS_MODULE(ofctrl);
35
36 /* An OpenFlow flow. */
37 struct ovn_flow {
38     /* Key. */
39     struct hmap_node hmap_node;
40     uint8_t table_id;
41     uint16_t priority;
42     struct match match;
43
44     /* Data. */
45     struct ofpact *ofpacts;
46     size_t ofpacts_len;
47 };
48
49 static uint32_t ovn_flow_hash(const struct ovn_flow *);
50 static struct ovn_flow *ovn_flow_lookup(struct hmap *flow_table,
51                                         const struct ovn_flow *target);
52 static char *ovn_flow_to_string(const struct ovn_flow *);
53 static void ovn_flow_log(const struct ovn_flow *, const char *action);
54 static void ovn_flow_destroy(struct ovn_flow *);
55
56 /* OpenFlow connection to the switch. */
57 static struct rconn *swconn;
58
59 /* Last seen sequence number for 'swconn'.  When this differs from
60  * rconn_get_connection_seqno(rconn), 'swconn' has reconnected. */
61 static unsigned int seqno;
62
63 /* Counter for in-flight OpenFlow messages on 'swconn'.  We only send a new
64  * round of flow table modifications to the switch when the counter falls to
65  * zero, to avoid unbounded buffering. */
66 static struct rconn_packet_counter *tx_counter;
67
68 /* Flow table of "struct ovn_flow"s, that holds the flow table currently
69  * installed in the switch. */
70 static struct hmap installed_flows;
71
72 static void ovn_flow_table_clear(struct hmap *flow_table);
73 static void ovn_flow_table_destroy(struct hmap *flow_table);
74
75 static void ofctrl_update_flows(struct hmap *desired_flows);
76 static void ofctrl_recv(const struct ofpbuf *msg);
77
78 void
79 ofctrl_init(void)
80 {
81     swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION);
82     tx_counter = rconn_packet_counter_create();
83     hmap_init(&installed_flows);
84 }
85
86 /* Attempts to update the OpenFlow flows in bridge 'br_int' to those in
87  * 'flow_table'.  Removes all of the flows from 'flow_table' and frees them.
88  *
89  * The flow table will only be updated if we've got an OpenFlow connection to
90  * 'br_int' and it's not backlogged.  Otherwise, it'll have to wait until the
91  * next iteration. */
92 void
93 ofctrl_run(const struct ovsrec_bridge *br_int, struct hmap *flow_table)
94 {
95     char *target;
96     target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name);
97     if (strcmp(target, rconn_get_target(swconn))) {
98         VLOG_INFO("%s: connecting to switch", target);
99         rconn_connect(swconn, target, target);
100     }
101     free(target);
102
103     rconn_run(swconn);
104
105     if (!rconn_is_connected(swconn)) {
106         goto exit;
107     }
108     if (!rconn_packet_counter_n_packets(tx_counter)) {
109         ofctrl_update_flows(flow_table);
110     }
111
112     for (int i = 0; i < 50; i++) {
113         struct ofpbuf *msg = rconn_recv(swconn);
114         if (!msg) {
115             break;
116         }
117
118         ofctrl_recv(msg);
119         ofpbuf_delete(msg);
120     }
121
122 exit:
123     ovn_flow_table_clear(flow_table);
124 }
125
126 void
127 ofctrl_wait(void)
128 {
129     rconn_run_wait(swconn);
130     rconn_recv_wait(swconn);
131 }
132
133 void
134 ofctrl_destroy(void)
135 {
136     rconn_destroy(swconn);
137     ovn_flow_table_destroy(&installed_flows);
138     rconn_packet_counter_destroy(tx_counter);
139 }
140 \f
141 static void
142 queue_msg(struct ofpbuf *msg)
143 {
144     rconn_send(swconn, msg, tx_counter);
145 }
146
147 static void
148 ofctrl_recv(const struct ofpbuf *msg)
149 {
150     enum ofptype type;
151     struct ofpbuf b;
152
153     b = *msg;
154     if (ofptype_pull(&type, &b)) {
155         return;
156     }
157
158     switch (type) {
159     case OFPTYPE_ECHO_REQUEST:
160         queue_msg(make_echo_reply(msg->data));
161         break;
162
163     case OFPTYPE_ECHO_REPLY:
164     case OFPTYPE_PACKET_IN:
165     case OFPTYPE_PORT_STATUS:
166     case OFPTYPE_FLOW_REMOVED:
167         /* Nothing to do. */
168         break;
169
170     case OFPTYPE_HELLO:
171     case OFPTYPE_ERROR:
172     case OFPTYPE_FEATURES_REQUEST:
173     case OFPTYPE_FEATURES_REPLY:
174     case OFPTYPE_GET_CONFIG_REQUEST:
175     case OFPTYPE_GET_CONFIG_REPLY:
176     case OFPTYPE_SET_CONFIG:
177     case OFPTYPE_PACKET_OUT:
178     case OFPTYPE_FLOW_MOD:
179     case OFPTYPE_GROUP_MOD:
180     case OFPTYPE_PORT_MOD:
181     case OFPTYPE_TABLE_MOD:
182     case OFPTYPE_BARRIER_REQUEST:
183     case OFPTYPE_BARRIER_REPLY:
184     case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
185     case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
186     case OFPTYPE_DESC_STATS_REQUEST:
187     case OFPTYPE_DESC_STATS_REPLY:
188     case OFPTYPE_FLOW_STATS_REQUEST:
189     case OFPTYPE_FLOW_STATS_REPLY:
190     case OFPTYPE_AGGREGATE_STATS_REQUEST:
191     case OFPTYPE_AGGREGATE_STATS_REPLY:
192     case OFPTYPE_TABLE_STATS_REQUEST:
193     case OFPTYPE_TABLE_STATS_REPLY:
194     case OFPTYPE_PORT_STATS_REQUEST:
195     case OFPTYPE_PORT_STATS_REPLY:
196     case OFPTYPE_QUEUE_STATS_REQUEST:
197     case OFPTYPE_QUEUE_STATS_REPLY:
198     case OFPTYPE_PORT_DESC_STATS_REQUEST:
199     case OFPTYPE_PORT_DESC_STATS_REPLY:
200     case OFPTYPE_ROLE_REQUEST:
201     case OFPTYPE_ROLE_REPLY:
202     case OFPTYPE_ROLE_STATUS:
203     case OFPTYPE_SET_FLOW_FORMAT:
204     case OFPTYPE_FLOW_MOD_TABLE_ID:
205     case OFPTYPE_SET_PACKET_IN_FORMAT:
206     case OFPTYPE_FLOW_AGE:
207     case OFPTYPE_SET_CONTROLLER_ID:
208     case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
209     case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
210     case OFPTYPE_FLOW_MONITOR_CANCEL:
211     case OFPTYPE_FLOW_MONITOR_PAUSED:
212     case OFPTYPE_FLOW_MONITOR_RESUMED:
213     case OFPTYPE_GET_ASYNC_REQUEST:
214     case OFPTYPE_GET_ASYNC_REPLY:
215     case OFPTYPE_SET_ASYNC_CONFIG:
216     case OFPTYPE_METER_MOD:
217     case OFPTYPE_GROUP_STATS_REQUEST:
218     case OFPTYPE_GROUP_STATS_REPLY:
219     case OFPTYPE_GROUP_DESC_STATS_REQUEST:
220     case OFPTYPE_GROUP_DESC_STATS_REPLY:
221     case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
222     case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
223     case OFPTYPE_METER_STATS_REQUEST:
224     case OFPTYPE_METER_STATS_REPLY:
225     case OFPTYPE_METER_CONFIG_STATS_REQUEST:
226     case OFPTYPE_METER_CONFIG_STATS_REPLY:
227     case OFPTYPE_METER_FEATURES_STATS_REQUEST:
228     case OFPTYPE_METER_FEATURES_STATS_REPLY:
229     case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
230     case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
231     case OFPTYPE_TABLE_DESC_REQUEST:
232     case OFPTYPE_TABLE_DESC_REPLY:
233     case OFPTYPE_BUNDLE_CONTROL:
234     case OFPTYPE_BUNDLE_ADD_MESSAGE:
235     case OFPTYPE_NXT_GENEVE_TABLE_MOD:
236     case OFPTYPE_NXT_GENEVE_TABLE_REQUEST:
237     case OFPTYPE_NXT_GENEVE_TABLE_REPLY:
238     default:
239         /* Messages that are generally unexpected. */
240         if (VLOG_IS_DBG_ENABLED()) {
241             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
242
243             char *s = ofp_to_string(msg->data, msg->size, 2);
244             VLOG_DBG_RL(&rl, "OpenFlow packet ignored: %s", s);
245             free(s);
246         }
247     }
248 }
249 \f
250 /* Flow table interface to the rest of ovn-controller. */
251
252 /* Adds a flow to 'desired_flows' with the specified 'match' and 'actions' to
253  * the OpenFlow table numbered 'table_id' with the given 'priority'.  The
254  * caller retains ownership of 'match' and 'actions'.
255  *
256  * This just assembles the desired flow table in memory.  Nothing is actually
257  * sent to the switch until a later call to ofctrl_run().
258  *
259  * The caller should initialize its own hmap to hold the flows. */
260 void
261 ofctrl_add_flow(struct hmap *desired_flows,
262                 uint8_t table_id, uint16_t priority,
263                 const struct match *match, const struct ofpbuf *actions)
264 {
265     struct ovn_flow *f = xmalloc(sizeof *f);
266     f->table_id = table_id;
267     f->priority = priority;
268     f->match = *match;
269     f->ofpacts = xmemdup(actions->data, actions->size);
270     f->ofpacts_len = actions->size;
271     f->hmap_node.hash = ovn_flow_hash(f);
272
273     if (ovn_flow_lookup(desired_flows, f)) {
274         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
275         if (!VLOG_DROP_INFO(&rl)) {
276             char *s = ovn_flow_to_string(f);
277             VLOG_INFO("dropping duplicate flow: %s", s);
278             free(s);
279         }
280
281         ovn_flow_destroy(f);
282         return;
283     }
284
285     hmap_insert(desired_flows, &f->hmap_node, f->hmap_node.hash);
286 }
287 \f
288 /* ovn_flow. */
289
290 /* Returns a hash of the key in 'f'. */
291 static uint32_t
292 ovn_flow_hash(const struct ovn_flow *f)
293 {
294     return hash_2words((f->table_id << 16) | f->priority,
295                        match_hash(&f->match, 0));
296
297 }
298
299 /* Finds and returns an ovn_flow in 'flow_table' whose key is identical to
300  * 'target''s key, or NULL if there is none. */
301 static struct ovn_flow *
302 ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target)
303 {
304     struct ovn_flow *f;
305
306     HMAP_FOR_EACH_WITH_HASH (f, hmap_node, target->hmap_node.hash,
307                              flow_table) {
308         if (f->table_id == target->table_id
309             && f->priority == target->priority
310             && match_equal(&f->match, &target->match)) {
311             return f;
312         }
313     }
314     return NULL;
315 }
316
317 static char *
318 ovn_flow_to_string(const struct ovn_flow *f)
319 {
320     struct ds s = DS_EMPTY_INITIALIZER;
321     ds_put_format(&s, "table_id=%"PRIu8", ", f->table_id);
322     ds_put_format(&s, "priority=%"PRIu16", ", f->priority);
323     match_format(&f->match, &s, OFP_DEFAULT_PRIORITY);
324     ds_put_cstr(&s, ", actions=");
325     ofpacts_format(f->ofpacts, f->ofpacts_len, &s);
326     return ds_steal_cstr(&s);
327 }
328
329 static void
330 ovn_flow_log(const struct ovn_flow *f, const char *action)
331 {
332     if (VLOG_IS_DBG_ENABLED()) {
333         char *s = ovn_flow_to_string(f);
334         VLOG_DBG("%s flow: %s", action, s);
335         free(s);
336     }
337 }
338
339 static void
340 ovn_flow_destroy(struct ovn_flow *f)
341 {
342     if (f) {
343         free(f->ofpacts);
344         free(f);
345     }
346 }
347 \f
348 /* Flow tables of struct ovn_flow. */
349
350 static void
351 ovn_flow_table_clear(struct hmap *flow_table)
352 {
353     struct ovn_flow *f, *next;
354     HMAP_FOR_EACH_SAFE (f, next, hmap_node, flow_table) {
355         hmap_remove(flow_table, &f->hmap_node);
356         ovn_flow_destroy(f);
357     }
358 }
359 static void
360 ovn_flow_table_destroy(struct hmap *flow_table)
361 {
362     ovn_flow_table_clear(flow_table);
363     hmap_destroy(flow_table);
364 }
365 \f
366 /* Flow table update. */
367
368 static void
369 queue_flow_mod(struct ofputil_flow_mod *fm)
370 {
371     fm->buffer_id = UINT32_MAX;
372     fm->out_port = OFPP_ANY;
373     fm->out_group = OFPG_ANY;
374     queue_msg(ofputil_encode_flow_mod(fm, OFPUTIL_P_OF13_OXM));
375 }
376
377 static void
378 ofctrl_update_flows(struct hmap *desired_flows)
379 {
380     /* If we've (re)connected, don't make any assumptions about the flows in
381      * the switch: delete all of them.  (We'll immediately repopulate it
382      * below.) */
383     if (seqno != rconn_get_connection_seqno(swconn)) {
384         seqno = rconn_get_connection_seqno(swconn);
385
386         /* Send a flow_mod to delete all flows. */
387         struct ofputil_flow_mod fm = {
388             .match = MATCH_CATCHALL_INITIALIZER,
389             .table_id = OFPTT_ALL,
390             .command = OFPFC_DELETE,
391         };
392         queue_flow_mod(&fm);
393         VLOG_DBG("clearing all flows");
394
395         /* Clear installed_flows, to match the state of the switch. */
396         ovn_flow_table_clear(&installed_flows);
397     }
398
399     /* Iterate through all of the installed flows.  If any of them are no
400      * longer desired, delete them; if any of them should have different
401      * actions, update them. */
402     struct ovn_flow *i, *next;
403     HMAP_FOR_EACH_SAFE (i, next, hmap_node, &installed_flows) {
404         struct ovn_flow *d = ovn_flow_lookup(desired_flows, i);
405         if (!d) {
406             /* Installed flow is no longer desirable.  Delete it from the
407              * switch and from installed_flows. */
408             struct ofputil_flow_mod fm = {
409                 .match = i->match,
410                 .priority = i->priority,
411                 .table_id = i->table_id,
412                 .command = OFPFC_DELETE_STRICT,
413             };
414             queue_flow_mod(&fm);
415             ovn_flow_log(i, "removing");
416
417             hmap_remove(&installed_flows, &i->hmap_node);
418             ovn_flow_destroy(i);
419         } else {
420             if (!ofpacts_equal(i->ofpacts, i->ofpacts_len,
421                                d->ofpacts, d->ofpacts_len)) {
422                 /* Update actions in installed flow. */
423                 struct ofputil_flow_mod fm = {
424                     .match = i->match,
425                     .priority = i->priority,
426                     .table_id = i->table_id,
427                     .ofpacts = d->ofpacts,
428                     .ofpacts_len = d->ofpacts_len,
429                     .command = OFPFC_MODIFY_STRICT,
430                 };
431                 queue_flow_mod(&fm);
432                 ovn_flow_log(i, "updating");
433
434                 /* Replace 'i''s actions by 'd''s. */
435                 free(i->ofpacts);
436                 i->ofpacts = d->ofpacts;
437                 i->ofpacts_len = d->ofpacts_len;
438                 d->ofpacts = NULL;
439                 d->ofpacts_len = 0;
440             }
441
442             hmap_remove(desired_flows, &d->hmap_node);
443             ovn_flow_destroy(d);
444         }
445     }
446
447     /* The previous loop removed from 'desired_flows' all of the flows that are
448      * already installed.  Thus, any flows remaining in 'desired_flows' need to
449      * be added to the flow table. */
450     struct ovn_flow *d;
451     HMAP_FOR_EACH_SAFE (d, next, hmap_node, desired_flows) {
452         /* Send flow_mod to add flow. */
453         struct ofputil_flow_mod fm = {
454             .match = d->match,
455             .priority = d->priority,
456             .table_id = d->table_id,
457             .ofpacts = d->ofpacts,
458             .ofpacts_len = d->ofpacts_len,
459             .command = OFPFC_ADD,
460         };
461         queue_flow_mod(&fm);
462         ovn_flow_log(d, "adding");
463
464         /* Move 'd' from 'desired_flows' to installed_flows. */
465         hmap_remove(desired_flows, &d->hmap_node);
466         hmap_insert(&installed_flows, &d->hmap_node, d->hmap_node.hash);
467     }
468 }