2 * Copyright (c) 2008, 2009 Nicira Networks.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "fail-open.h"
22 #include "mac-learning.h"
29 #define THIS_MODULE VLM_fail_open
33 struct ofproto *ofproto;
34 struct rconn *controller;
36 int last_disconn_secs;
37 struct status_category *ss_cat;
40 /* Causes the switch to enter or leave fail-open mode, if appropriate. */
42 fail_open_run(struct fail_open *fo)
44 int disconn_secs = rconn_failure_duration(fo->controller);
45 bool open = disconn_secs >= fo->trigger_duration;
46 if (open != (fo->last_disconn_secs != 0)) {
50 VLOG_WARN("No longer in fail-open mode");
51 fo->last_disconn_secs = 0;
53 memset(&flow, 0, sizeof flow);
54 ofproto_delete_flow(fo->ofproto, &flow, OFPFW_ALL, 70000);
56 VLOG_WARN("Could not connect to controller for %d seconds, "
57 "failing open", disconn_secs);
58 fo->last_disconn_secs = disconn_secs;
60 /* Flush all OpenFlow and datapath flows. We will set up our
61 * fail-open rule from fail_open_flushed() when
62 * ofproto_flush_flows() calls back to us. */
63 ofproto_flush_flows(fo->ofproto);
65 } else if (open && disconn_secs > fo->last_disconn_secs + 60) {
66 VLOG_INFO("Still in fail-open mode after %d seconds disconnected "
67 "from controller", disconn_secs);
68 fo->last_disconn_secs = disconn_secs;
73 fail_open_wait(struct fail_open *fo UNUSED)
79 fail_open_flushed(struct fail_open *fo)
81 int disconn_secs = rconn_failure_duration(fo->controller);
82 bool open = disconn_secs >= fo->trigger_duration;
84 union ofp_action action;
87 /* Set up a flow that matches every packet and directs them to
89 memset(&action, 0, sizeof action);
90 action.type = htons(OFPAT_OUTPUT);
91 action.output.len = htons(sizeof action);
92 action.output.port = htons(OFPP_NORMAL);
93 memset(&flow, 0, sizeof flow);
94 ofproto_add_flow(fo->ofproto, &flow, OFPFW_ALL, 70000,
100 fail_open_status_cb(struct status_reply *sr, void *fo_)
102 struct fail_open *fo = fo_;
103 int cur_duration = rconn_failure_duration(fo->controller);
105 status_reply_put(sr, "trigger-duration=%d", fo->trigger_duration);
106 status_reply_put(sr, "current-duration=%d", cur_duration);
107 status_reply_put(sr, "triggered=%s",
108 cur_duration >= fo->trigger_duration ? "true" : "false");
112 fail_open_create(struct ofproto *ofproto,
113 int trigger_duration, struct switch_status *switch_status,
114 struct rconn *controller)
116 struct fail_open *fo = xmalloc(sizeof *fo);
117 fo->ofproto = ofproto;
118 fo->controller = controller;
119 fo->trigger_duration = trigger_duration;
120 fo->last_disconn_secs = 0;
121 fo->ss_cat = switch_status_register(switch_status, "fail-open",
122 fail_open_status_cb, fo);
127 fail_open_set_trigger_duration(struct fail_open *fo, int trigger_duration)
129 fo->trigger_duration = trigger_duration;
133 fail_open_destroy(struct fail_open *fo)
136 /* We don't own fo->controller. */
137 switch_status_unregister(fo->ss_cat);