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 (or switch failed "
57 "controller's post-connection admission control "
58 "policy) for %d seconds, failing open", disconn_secs);
59 fo->last_disconn_secs = disconn_secs;
61 /* Flush all OpenFlow and datapath flows. We will set up our
62 * fail-open rule from fail_open_flushed() when
63 * ofproto_flush_flows() calls back to us. */
64 ofproto_flush_flows(fo->ofproto);
66 } else if (open && disconn_secs > fo->last_disconn_secs + 60) {
67 VLOG_INFO("Still in fail-open mode after %d seconds disconnected "
68 "from controller", disconn_secs);
69 fo->last_disconn_secs = disconn_secs;
74 fail_open_wait(struct fail_open *fo UNUSED)
80 fail_open_flushed(struct fail_open *fo)
82 int disconn_secs = rconn_failure_duration(fo->controller);
83 bool open = disconn_secs >= fo->trigger_duration;
85 union ofp_action action;
88 /* Set up a flow that matches every packet and directs them to
90 memset(&action, 0, sizeof action);
91 action.type = htons(OFPAT_OUTPUT);
92 action.output.len = htons(sizeof action);
93 action.output.port = htons(OFPP_NORMAL);
94 memset(&flow, 0, sizeof flow);
95 ofproto_add_flow(fo->ofproto, &flow, OFPFW_ALL, 70000,
101 fail_open_status_cb(struct status_reply *sr, void *fo_)
103 struct fail_open *fo = fo_;
104 int cur_duration = rconn_failure_duration(fo->controller);
106 status_reply_put(sr, "trigger-duration=%d", fo->trigger_duration);
107 status_reply_put(sr, "current-duration=%d", cur_duration);
108 status_reply_put(sr, "triggered=%s",
109 cur_duration >= fo->trigger_duration ? "true" : "false");
113 fail_open_create(struct ofproto *ofproto,
114 int trigger_duration, struct switch_status *switch_status,
115 struct rconn *controller)
117 struct fail_open *fo = xmalloc(sizeof *fo);
118 fo->ofproto = ofproto;
119 fo->controller = controller;
120 fo->trigger_duration = trigger_duration;
121 fo->last_disconn_secs = 0;
122 fo->ss_cat = switch_status_register(switch_status, "fail-open",
123 fail_open_status_cb, fo);
128 fail_open_set_trigger_duration(struct fail_open *fo, int trigger_duration)
130 fo->trigger_duration = trigger_duration;
134 fail_open_destroy(struct fail_open *fo)
137 /* We don't own fo->controller. */
138 switch_status_unregister(fo->ss_cat);