Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 241 lines (208 sloc) 6.396 kB
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
1 /*
e85b2b9 licence: update COPYING file and all file headers
Jiri Pirko authored
2 * teamd_runner_activebackup.c - Active-backup runners
3 * Copyright (C) 2012 Jiri Pirko <jpirko@redhat.com>
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
4 *
e85b2b9 licence: update COPYING file and all file headers
Jiri Pirko authored
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
18 */
19
20 #include <stdbool.h>
2a5a230 teamd: push link watch out of runner code
Jiri Pirko authored
21 #include <stdint.h>
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <sys/socket.h>
26 #include <linux/netdevice.h>
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
27 #include <jansson.h>
28 #include <limits.h>
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
29 #include <team.h>
30
31 #include "teamd.h"
32
33 struct abl_priv {
10fb3b3 @jpirko teamd: convert option watch to use events
authored
34 char old_active_hwaddr[MAX_ADDR_LEN];
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
35 };
36
37 static struct abl_priv *abl_priv(struct teamd_context *ctx)
38 {
39 return (struct abl_priv *) ctx->runner_priv;
40 }
41
8287e97 @jpirko teamd: ab: user priority from option rather than from config
authored
42 static int get_port_prio(struct teamd_context *ctx, struct teamd_port *tdport)
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
43 {
44 int prio;
45 int err;
46
8287e97 @jpirko teamd: ab: user priority from option rather than from config
authored
47 err = team_get_port_priority(ctx->th, tdport->ifindex, &prio);
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
48 if (err) {
8287e97 @jpirko teamd: ab: user priority from option rather than from config
authored
49 teamd_log_warn("%s: Can't get port priority. Using default.",
50 tdport->ifname);
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
51 return 0; /* return default priority */
52 }
53 return prio;
54 }
55
4cd6a67 teamd_runner_ab: allow ports to be "sticky"
Jiri Pirko authored
56 static bool is_port_sticky(struct teamd_context *ctx, const char *port_name)
57 {
58 int sticky;
59 int err;
60
61 err = json_unpack(ctx->config_json, "{s:{s:{s:b}}}", "ports", port_name,
62 "sticky", &sticky);
63 if (err) {
ddba2f4 teamd: Consolidate port related prints
Jiri Pirko authored
64 teamd_log_dbg("%s: Using default port stickiness.", port_name);
4cd6a67 teamd_runner_ab: allow ports to be "sticky"
Jiri Pirko authored
65 return false; /* return default stickiness */
66 }
67 return sticky;
68 }
69
8e225d2 teamd: ab: change change_active_port() to return error
Jiri Pirko authored
70 static int change_active_port(struct teamd_context *ctx,
71 struct teamd_port *old_tdport,
72 struct teamd_port *new_tdport)
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
73 {
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
74 uint32_t new_active_ifindex = new_tdport->ifindex;
75 uint32_t old_active_ifindex = 0;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
76 int err;
77
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
78 if (old_tdport) {
79 old_active_ifindex = old_tdport->ifindex;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
80 err = team_hwaddr_set(ctx->th, old_active_ifindex,
81 abl_priv(ctx)->old_active_hwaddr,
82 ctx->hwaddr_len);
8e225d2 teamd: ab: change change_active_port() to return error
Jiri Pirko authored
83 if (err) {
84 teamd_log_err("Failed to set old active original hardware address.");
85 return err;
86 }
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
87 }
88
89 err = team_set_active_port(ctx->th, new_active_ifindex);
8e225d2 teamd: ab: change change_active_port() to return error
Jiri Pirko authored
90 if (err) {
91 teamd_log_err("Failed to set active port.");
92 return err;
93 }
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
94
fbedcde teamd: kill team_hwaddr_get() calls and replace them with ifinfo data
Jiri Pirko authored
95 memcpy(abl_priv(ctx)->old_active_hwaddr,
96 team_get_ifinfo_hwaddr(new_tdport->team_ifinfo),
97 ctx->hwaddr_len);
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
98
fbedcde teamd: kill team_hwaddr_get() calls and replace them with ifinfo data
Jiri Pirko authored
99 err = team_hwaddr_set(ctx->th, new_active_ifindex, ctx->hwaddr,
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
100 ctx->hwaddr_len);
8e225d2 teamd: ab: change change_active_port() to return error
Jiri Pirko authored
101 if (err) {
102 teamd_log_err("Failed to set new active hardware address.");
103 return err;
104 }
105 return 0;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
106 }
107
92ffaab @jpirko teamd: ab: expose runner state json
authored
108 static int abl_get_active_tdport(struct teamd_context *ctx,
109 struct teamd_port **pactive_tdport)
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
110 {
92ffaab @jpirko teamd: ab: expose runner state json
authored
111 int err;
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
112 uint32_t ifindex;
92ffaab @jpirko teamd: ab: expose runner state json
authored
113
114 err = team_get_active_port(ctx->th, &ifindex);
115 if (err) {
116 teamd_log_err("Failed to get active port.");
117 return err;
118 }
119 *pactive_tdport = teamd_get_port(ctx, ifindex);
120 return 0;
121 }
122
123 static int link_watch_handler(struct teamd_context *ctx)
124 {
4bf5aae teamd: ab: use teamd_for_each_tdport
Jiri Pirko authored
125 struct teamd_port *tdport;
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
126 struct teamd_port *active_tdport;
127 struct teamd_port *best_tdport = NULL;
4ca092d fix uninitialized variable warnings
Jiri Pirko authored
128 uint32_t best_speed = 0;
129 uint8_t best_duplex = 0;
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
130 int best_prio = INT_MIN;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
131 int err;
132
92ffaab @jpirko teamd: ab: expose runner state json
authored
133 err = abl_get_active_tdport(ctx, &active_tdport);
134 if (err)
e5dc394 allow change handlers to return error and propagate it
Jiri Pirko authored
135 return err;
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
136 if (active_tdport)
137 teamd_log_dbg("Current active port: \"%s\" (ifindex \"%d\", prio \"%d\").",
138 active_tdport->ifname, active_tdport->ifindex,
8287e97 @jpirko teamd: ab: user priority from option rather than from config
authored
139 get_port_prio(ctx, active_tdport));
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
140
4bf5aae teamd: ab: use teamd_for_each_tdport
Jiri Pirko authored
141 teamd_for_each_tdport(tdport, ctx) {
142 struct team_port *port = tdport->team_port;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
143
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
144 if (teamd_link_watch_port_up(ctx, tdport)) {
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
145 uint32_t speed = team_get_port_speed(port);
146 uint8_t duplex = team_get_port_duplex(port);
8287e97 @jpirko teamd: ab: user priority from option rather than from config
authored
147 int prio = get_port_prio(ctx, tdport);
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
148
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
149 if (!best_tdport ||
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
150 (prio > best_prio) ||
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
151 (speed > best_speed) ||
152 (speed == best_speed && duplex > best_duplex)) {
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
153 best_tdport = tdport;
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
154 best_prio = prio;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
155 best_speed = speed;
156 best_duplex = duplex;
157 }
158 }
159 }
160
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
161 if (!best_tdport || best_tdport == active_tdport)
162 return 0;
4cd6a67 teamd_runner_ab: allow ports to be "sticky"
Jiri Pirko authored
163
bdbbf6a teamd_runner_ab: add priority based port selection
Jiri Pirko authored
164 teamd_log_dbg("Found best port: \"%s\" (ifindex \"%d\", prio \"%d\").",
d21be40 teamd: use teamd_port struct instead of ifindex to identify port inte…
Jiri Pirko authored
165 best_tdport->ifname, best_tdport->ifindex, best_prio);
166 if (!active_tdport ||
167 !teamd_link_watch_port_up(ctx, active_tdport) ||
168 !is_port_sticky(ctx, active_tdport->ifname)) {
169 teamd_log_info("Changing active port to \"%s\".",
170 best_tdport->ifname);
8e225d2 teamd: ab: change change_active_port() to return error
Jiri Pirko authored
171 err = change_active_port(ctx, active_tdport, best_tdport);
172 if (err)
173 return err;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
174 }
e5dc394 allow change handlers to return error and propagate it
Jiri Pirko authored
175 return 0;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
176 }
177
c296f4e @jpirko teamd: ab use port_link_changed event op to look for port link changes
authored
178 static int abl_port_link_changed(struct teamd_context *ctx,
179 struct teamd_port *tdport, void *priv)
180 {
181 return link_watch_handler(ctx);
182 }
183
10fb3b3 @jpirko teamd: convert option watch to use events
authored
184 static int abl_prio_option_changed(struct teamd_context *ctx,
185 struct team_option *option, void *priv)
34710d0 @jpirko teamd: ab: watch for priority changes
authored
186 {
187 return link_watch_handler(ctx);
188 }
189
604b1c4 @jpirko teamd: ab: convert to use generic event watch to watch prio change
authored
190 static const struct teamd_event_watch_ops abl_event_watch_ops = {
c296f4e @jpirko teamd: ab use port_link_changed event op to look for port link changes
authored
191 .port_link_changed = abl_port_link_changed,
10fb3b3 @jpirko teamd: convert option watch to use events
authored
192 .option_changed = abl_prio_option_changed,
604b1c4 @jpirko teamd: ab: convert to use generic event watch to watch prio change
authored
193 .option_changed_match_name = "priority",
34710d0 @jpirko teamd: ab: watch for priority changes
authored
194 };
195
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
196 static int abl_init(struct teamd_context *ctx)
197 {
34710d0 @jpirko teamd: ab: watch for priority changes
authored
198 int err;
199
604b1c4 @jpirko teamd: ab: convert to use generic event watch to watch prio change
authored
200 err = teamd_event_watch_register(ctx, &abl_event_watch_ops, NULL);
201 if (err) {
202 teamd_log_err("Failed to register event watch.");
34710d0 @jpirko teamd: ab: watch for priority changes
authored
203 return err;
604b1c4 @jpirko teamd: ab: convert to use generic event watch to watch prio change
authored
204 }
2a5a230 teamd: push link watch out of runner code
Jiri Pirko authored
205 return 0;
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
206 }
207
208 static void abl_fini(struct teamd_context *ctx)
209 {
604b1c4 @jpirko teamd: ab: convert to use generic event watch to watch prio change
authored
210 teamd_event_watch_unregister(ctx, &abl_event_watch_ops, NULL);
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
211 }
212
92ffaab @jpirko teamd: ab: expose runner state json
authored
213 static int abl_state_json_dump(struct teamd_context *ctx,
214 json_t **pstate_json, void *priv)
215 {
216 int err;
217 struct teamd_port *active_tdport;
218 json_t *state_json;
219 char *active_port;
220
221 err = abl_get_active_tdport(ctx, &active_tdport);
222 if (err)
223 return err;
224
225 active_port = active_tdport ? active_tdport->ifname : "";
226 state_json = json_pack("{s:s}", "active_port", active_port);
227 if (!state_json)
228 return -ENOMEM;
229 *pstate_json = state_json;
230 return 0;
231 }
232
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
233 const struct teamd_runner teamd_runner_activebackup = {
92ffaab @jpirko teamd: ab: expose runner state json
authored
234 .name = "activebackup",
235 .team_mode_name = "activebackup",
236 .priv_size = sizeof(struct abl_priv),
237 .init = abl_init,
238 .fini = abl_fini,
239 .state_json_dump = abl_state_json_dump,
49819e5 teamd: add activebackup_linkmon runner
Jiri Pirko authored
240 };
Something went wrong with that request. Please try again.