ia64/linux-2.6.18-xen.hg

view Documentation/networking/ifenslave.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /* Mode: C;
2 * ifenslave.c: Configure network interfaces for parallel routing.
3 *
4 * This program controls the Linux implementation of running multiple
5 * network interfaces in parallel.
6 *
7 * Author: Donald Becker <becker@cesdis.gsfc.nasa.gov>
8 * Copyright 1994-1996 Donald Becker
9 *
10 * This program is free software; you can redistribute it
11 * and/or modify it under the terms of the GNU General Public
12 * License as published by the Free Software Foundation.
13 *
14 * The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
15 * Center of Excellence in Space Data and Information Sciences
16 * Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
17 *
18 * Changes :
19 * - 2000/10/02 Willy Tarreau <willy at meta-x.org> :
20 * - few fixes. Master's MAC address is now correctly taken from
21 * the first device when not previously set ;
22 * - detach support : call BOND_RELEASE to detach an enslaved interface.
23 * - give a mini-howto from command-line help : # ifenslave -h
24 *
25 * - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> :
26 * - Master is now brought down before setting the MAC address. In
27 * the 2.4 kernel you can't change the MAC address while the device is
28 * up because you get EBUSY.
29 *
30 * - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com>
31 * - Added the ability to change the active interface on a mode 1 bond
32 * at runtime.
33 *
34 * - 2001/10/23 Chad N. Tindel <ctindel at ieee dot org> :
35 * - No longer set the MAC address of the master. The bond device will
36 * take care of this itself
37 * - Try the SIOC*** versions of the bonding ioctls before using the
38 * old versions
39 * - 2002/02/18 Erik Habbinga <erik_habbinga @ hp dot com> :
40 * - ifr2.ifr_flags was not initialized in the hwaddr_notset case,
41 * SIOCGIFFLAGS now called before hwaddr_notset test
42 *
43 * - 2002/10/31 Tony Cureington <tony.cureington * hp_com> :
44 * - If the master does not have a hardware address when the first slave
45 * is enslaved, the master is assigned the hardware address of that
46 * slave - there is a comment in bonding.c stating "ifenslave takes
47 * care of this now." This corrects the problem of slaves having
48 * different hardware addresses in active-backup mode when
49 * multiple interfaces are specified on a single ifenslave command
50 * (ifenslave bond0 eth0 eth1).
51 *
52 * - 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
53 * Shmulik Hen <shmulik.hen at intel dot com>
54 * - Moved setting the slave's mac address and openning it, from
55 * the application to the driver. This enables support of modes
56 * that need to use the unique mac address of each slave.
57 * The driver also takes care of closing the slave and restoring its
58 * original mac address upon release.
59 * In addition, block possibility of enslaving before the master is up.
60 * This prevents putting the system in an undefined state.
61 *
62 * - 2003/05/01 - Amir Noam <amir.noam at intel dot com>
63 * - Added ABI version control to restore compatibility between
64 * new/old ifenslave and new/old bonding.
65 * - Prevent adding an adapter that is already a slave.
66 * Fixes the problem of stalling the transmission and leaving
67 * the slave in a down state.
68 *
69 * - 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
70 * - Prevent enslaving if the bond device is down.
71 * Fixes the problem of leaving the system in unstable state and
72 * halting when trying to remove the module.
73 * - Close socket on all abnormal exists.
74 * - Add versioning scheme that follows that of the bonding driver.
75 * current version is 1.0.0 as a base line.
76 *
77 * - 2003/05/22 - Jay Vosburgh <fubar at us dot ibm dot com>
78 * - ifenslave -c was broken; it's now fixed
79 * - Fixed problem with routes vanishing from master during enslave
80 * processing.
81 *
82 * - 2003/05/27 - Amir Noam <amir.noam at intel dot com>
83 * - Fix backward compatibility issues:
84 * For drivers not using ABI versions, slave was set down while
85 * it should be left up before enslaving.
86 * Also, master was not set down and the default set_mac_address()
87 * would fail and generate an error message in the system log.
88 * - For opt_c: slave should not be set to the master's setting
89 * while it is running. It was already set during enslave. To
90 * simplify things, it is now handled separately.
91 *
92 * - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
93 * - Code cleanup and style changes
94 * set version to 1.1.0
95 */
97 #define APP_VERSION "1.1.0"
98 #define APP_RELDATE "December 1, 2003"
99 #define APP_NAME "ifenslave"
101 static char *version =
102 APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ")\n"
103 "o Donald Becker (becker@cesdis.gsfc.nasa.gov).\n"
104 "o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n"
105 "o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n"
106 " (ctindel at ieee dot org).\n";
108 static const char *usage_msg =
109 "Usage: ifenslave [-f] <master-if> <slave-if> [<slave-if>...]\n"
110 " ifenslave -d <master-if> <slave-if> [<slave-if>...]\n"
111 " ifenslave -c <master-if> <slave-if>\n"
112 " ifenslave --help\n";
114 static const char *help_msg =
115 "\n"
116 " To create a bond device, simply follow these three steps :\n"
117 " - ensure that the required drivers are properly loaded :\n"
118 " # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n"
119 " - assign an IP address to the bond device :\n"
120 " # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
121 " - attach all the interfaces you need to the bond device :\n"
122 " # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n"
123 " If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
124 " interfaces attached AFTER this assignment will get the same MAC addr.\n"
125 " (except for ALB/TLB modes)\n"
126 "\n"
127 " To set the bond device down and automatically release all the slaves :\n"
128 " # ifconfig bond0 down\n"
129 "\n"
130 " To detach a dead interface without setting the bond device down :\n"
131 " # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n"
132 "\n"
133 " To change active slave :\n"
134 " # ifenslave {-c|--change-active} bond0 eth0\n"
135 "\n"
136 " To show master interface info\n"
137 " # ifenslave bond0\n"
138 "\n"
139 " To show all interfaces info\n"
140 " # ifenslave {-a|--all-interfaces}\n"
141 "\n"
142 " To be more verbose\n"
143 " # ifenslave {-v|--verbose} ...\n"
144 "\n"
145 " # ifenslave {-u|--usage} Show usage\n"
146 " # ifenslave {-V|--version} Show version\n"
147 " # ifenslave {-h|--help} This message\n"
148 "\n";
150 #include <unistd.h>
151 #include <stdlib.h>
152 #include <stdio.h>
153 #include <ctype.h>
154 #include <string.h>
155 #include <errno.h>
156 #include <fcntl.h>
157 #include <getopt.h>
158 #include <sys/types.h>
159 #include <sys/socket.h>
160 #include <sys/ioctl.h>
161 #include <linux/if.h>
162 #include <net/if_arp.h>
163 #include <linux/if_ether.h>
164 #include <linux/if_bonding.h>
165 #include <linux/sockios.h>
167 typedef unsigned long long u64; /* hack, so we may include kernel's ethtool.h */
168 typedef __uint32_t u32; /* ditto */
169 typedef __uint16_t u16; /* ditto */
170 typedef __uint8_t u8; /* ditto */
171 #include <linux/ethtool.h>
173 struct option longopts[] = {
174 /* { name has_arg *flag val } */
175 {"all-interfaces", 0, 0, 'a'}, /* Show all interfaces. */
176 {"change-active", 0, 0, 'c'}, /* Change the active slave. */
177 {"detach", 0, 0, 'd'}, /* Detach a slave interface. */
178 {"force", 0, 0, 'f'}, /* Force the operation. */
179 {"help", 0, 0, 'h'}, /* Give help */
180 {"usage", 0, 0, 'u'}, /* Give usage */
181 {"verbose", 0, 0, 'v'}, /* Report each action taken. */
182 {"version", 0, 0, 'V'}, /* Emit version information. */
183 { 0, 0, 0, 0}
184 };
186 /* Command-line flags. */
187 unsigned int
188 opt_a = 0, /* Show-all-interfaces flag. */
189 opt_c = 0, /* Change-active-slave flag. */
190 opt_d = 0, /* Detach a slave interface. */
191 opt_f = 0, /* Force the operation. */
192 opt_h = 0, /* Help */
193 opt_u = 0, /* Usage */
194 opt_v = 0, /* Verbose flag. */
195 opt_V = 0; /* Version */
197 int skfd = -1; /* AF_INET socket for ioctl() calls.*/
198 int abi_ver = 0; /* userland - kernel ABI version */
199 int hwaddr_set = 0; /* Master's hwaddr is set */
200 int saved_errno;
202 struct ifreq master_mtu, master_flags, master_hwaddr;
203 struct ifreq slave_mtu, slave_flags, slave_hwaddr;
205 struct dev_ifr {
206 struct ifreq *req_ifr;
207 char *req_name;
208 int req_type;
209 };
211 struct dev_ifr master_ifra[] = {
212 {&master_mtu, "SIOCGIFMTU", SIOCGIFMTU},
213 {&master_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS},
214 {&master_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR},
215 {NULL, "", 0}
216 };
218 struct dev_ifr slave_ifra[] = {
219 {&slave_mtu, "SIOCGIFMTU", SIOCGIFMTU},
220 {&slave_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS},
221 {&slave_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR},
222 {NULL, "", 0}
223 };
225 static void if_print(char *ifname);
226 static int get_drv_info(char *master_ifname);
227 static int get_if_settings(char *ifname, struct dev_ifr ifra[]);
228 static int get_slave_flags(char *slave_ifname);
229 static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr);
230 static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr);
231 static int set_slave_mtu(char *slave_ifname, int mtu);
232 static int set_if_flags(char *ifname, short flags);
233 static int set_if_up(char *ifname, short flags);
234 static int set_if_down(char *ifname, short flags);
235 static int clear_if_addr(char *ifname);
236 static int set_if_addr(char *master_ifname, char *slave_ifname);
237 static int change_active(char *master_ifname, char *slave_ifname);
238 static int enslave(char *master_ifname, char *slave_ifname);
239 static int release(char *master_ifname, char *slave_ifname);
240 #define v_print(fmt, args...) \
241 if (opt_v) \
242 fprintf(stderr, fmt, ## args )
244 int main(int argc, char *argv[])
245 {
246 char **spp, *master_ifname, *slave_ifname;
247 int c, i, rv;
248 int res = 0;
249 int exclusive = 0;
251 while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) {
252 switch (c) {
253 case 'a': opt_a++; exclusive++; break;
254 case 'c': opt_c++; exclusive++; break;
255 case 'd': opt_d++; exclusive++; break;
256 case 'f': opt_f++; exclusive++; break;
257 case 'h': opt_h++; exclusive++; break;
258 case 'u': opt_u++; exclusive++; break;
259 case 'v': opt_v++; break;
260 case 'V': opt_V++; exclusive++; break;
262 case '?':
263 fprintf(stderr, usage_msg);
264 res = 2;
265 goto out;
266 }
267 }
269 /* options check */
270 if (exclusive > 1) {
271 fprintf(stderr, usage_msg);
272 res = 2;
273 goto out;
274 }
276 if (opt_v || opt_V) {
277 printf(version);
278 if (opt_V) {
279 res = 0;
280 goto out;
281 }
282 }
284 if (opt_u) {
285 printf(usage_msg);
286 res = 0;
287 goto out;
288 }
290 if (opt_h) {
291 printf(usage_msg);
292 printf(help_msg);
293 res = 0;
294 goto out;
295 }
297 /* Open a basic socket */
298 if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
299 perror("socket");
300 res = 1;
301 goto out;
302 }
304 if (opt_a) {
305 if (optind == argc) {
306 /* No remaining args */
307 /* show all interfaces */
308 if_print((char *)NULL);
309 goto out;
310 } else {
311 /* Just show usage */
312 fprintf(stderr, usage_msg);
313 res = 2;
314 goto out;
315 }
316 }
318 /* Copy the interface name */
319 spp = argv + optind;
320 master_ifname = *spp++;
322 if (master_ifname == NULL) {
323 fprintf(stderr, usage_msg);
324 res = 2;
325 goto out;
326 }
328 /* exchange abi version with bonding module */
329 res = get_drv_info(master_ifname);
330 if (res) {
331 fprintf(stderr,
332 "Master '%s': Error: handshake with driver failed. "
333 "Aborting\n",
334 master_ifname);
335 goto out;
336 }
338 slave_ifname = *spp++;
340 if (slave_ifname == NULL) {
341 if (opt_d || opt_c) {
342 fprintf(stderr, usage_msg);
343 res = 2;
344 goto out;
345 }
347 /* A single arg means show the
348 * configuration for this interface
349 */
350 if_print(master_ifname);
351 goto out;
352 }
354 res = get_if_settings(master_ifname, master_ifra);
355 if (res) {
356 /* Probably a good reason not to go on */
357 fprintf(stderr,
358 "Master '%s': Error: get settings failed: %s. "
359 "Aborting\n",
360 master_ifname, strerror(res));
361 goto out;
362 }
364 /* check if master is indeed a master;
365 * if not then fail any operation
366 */
367 if (!(master_flags.ifr_flags & IFF_MASTER)) {
368 fprintf(stderr,
369 "Illegal operation; the specified interface '%s' "
370 "is not a master. Aborting\n",
371 master_ifname);
372 res = 1;
373 goto out;
374 }
376 /* check if master is up; if not then fail any operation */
377 if (!(master_flags.ifr_flags & IFF_UP)) {
378 fprintf(stderr,
379 "Illegal operation; the specified master interface "
380 "'%s' is not up.\n",
381 master_ifname);
382 res = 1;
383 goto out;
384 }
386 /* Only for enslaving */
387 if (!opt_c && !opt_d) {
388 sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family;
389 unsigned char *hwaddr =
390 (unsigned char *)master_hwaddr.ifr_hwaddr.sa_data;
392 /* The family '1' is ARPHRD_ETHER for ethernet. */
393 if (master_family != 1 && !opt_f) {
394 fprintf(stderr,
395 "Illegal operation: The specified master "
396 "interface '%s' is not ethernet-like.\n "
397 "This program is designed to work with "
398 "ethernet-like network interfaces.\n "
399 "Use the '-f' option to force the "
400 "operation.\n",
401 master_ifname);
402 res = 1;
403 goto out;
404 }
406 /* Check master's hw addr */
407 for (i = 0; i < 6; i++) {
408 if (hwaddr[i] != 0) {
409 hwaddr_set = 1;
410 break;
411 }
412 }
414 if (hwaddr_set) {
415 v_print("current hardware address of master '%s' "
416 "is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
417 "type %d\n",
418 master_ifname,
419 hwaddr[0], hwaddr[1],
420 hwaddr[2], hwaddr[3],
421 hwaddr[4], hwaddr[5],
422 master_family);
423 }
424 }
426 /* Accepts only one slave */
427 if (opt_c) {
428 /* change active slave */
429 res = get_slave_flags(slave_ifname);
430 if (res) {
431 fprintf(stderr,
432 "Slave '%s': Error: get flags failed. "
433 "Aborting\n",
434 slave_ifname);
435 goto out;
436 }
437 res = change_active(master_ifname, slave_ifname);
438 if (res) {
439 fprintf(stderr,
440 "Master '%s', Slave '%s': Error: "
441 "Change active failed\n",
442 master_ifname, slave_ifname);
443 }
444 } else {
445 /* Accept multiple slaves */
446 do {
447 if (opt_d) {
448 /* detach a slave interface from the master */
449 rv = get_slave_flags(slave_ifname);
450 if (rv) {
451 /* Can't work with this slave. */
452 /* remember the error and skip it*/
453 fprintf(stderr,
454 "Slave '%s': Error: get flags "
455 "failed. Skipping\n",
456 slave_ifname);
457 res = rv;
458 continue;
459 }
460 rv = release(master_ifname, slave_ifname);
461 if (rv) {
462 fprintf(stderr,
463 "Master '%s', Slave '%s': Error: "
464 "Release failed\n",
465 master_ifname, slave_ifname);
466 res = rv;
467 }
468 } else {
469 /* attach a slave interface to the master */
470 rv = get_if_settings(slave_ifname, slave_ifra);
471 if (rv) {
472 /* Can't work with this slave. */
473 /* remember the error and skip it*/
474 fprintf(stderr,
475 "Slave '%s': Error: get "
476 "settings failed: %s. "
477 "Skipping\n",
478 slave_ifname, strerror(rv));
479 res = rv;
480 continue;
481 }
482 rv = enslave(master_ifname, slave_ifname);
483 if (rv) {
484 fprintf(stderr,
485 "Master '%s', Slave '%s': Error: "
486 "Enslave failed\n",
487 master_ifname, slave_ifname);
488 res = rv;
489 }
490 }
491 } while ((slave_ifname = *spp++) != NULL);
492 }
494 out:
495 if (skfd >= 0) {
496 close(skfd);
497 }
499 return res;
500 }
502 static short mif_flags;
504 /* Get the inteface configuration from the kernel. */
505 static int if_getconfig(char *ifname)
506 {
507 struct ifreq ifr;
508 int metric, mtu; /* Parameters of the master interface. */
509 struct sockaddr dstaddr, broadaddr, netmask;
510 unsigned char *hwaddr;
512 strcpy(ifr.ifr_name, ifname);
513 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
514 return -1;
515 mif_flags = ifr.ifr_flags;
516 printf("The result of SIOCGIFFLAGS on %s is %x.\n",
517 ifname, ifr.ifr_flags);
519 strcpy(ifr.ifr_name, ifname);
520 if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
521 return -1;
522 printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",
523 ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
524 ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);
526 strcpy(ifr.ifr_name, ifname);
527 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
528 return -1;
530 /* Gotta convert from 'char' to unsigned for printf(). */
531 hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data;
532 printf("The result of SIOCGIFHWADDR is type %d "
533 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
534 ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
535 hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
537 strcpy(ifr.ifr_name, ifname);
538 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
539 metric = 0;
540 } else
541 metric = ifr.ifr_metric;
543 strcpy(ifr.ifr_name, ifname);
544 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
545 mtu = 0;
546 else
547 mtu = ifr.ifr_mtu;
549 strcpy(ifr.ifr_name, ifname);
550 if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) {
551 memset(&dstaddr, 0, sizeof(struct sockaddr));
552 } else
553 dstaddr = ifr.ifr_dstaddr;
555 strcpy(ifr.ifr_name, ifname);
556 if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) {
557 memset(&broadaddr, 0, sizeof(struct sockaddr));
558 } else
559 broadaddr = ifr.ifr_broadaddr;
561 strcpy(ifr.ifr_name, ifname);
562 if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) {
563 memset(&netmask, 0, sizeof(struct sockaddr));
564 } else
565 netmask = ifr.ifr_netmask;
567 return 0;
568 }
570 static void if_print(char *ifname)
571 {
572 char buff[1024];
573 struct ifconf ifc;
574 struct ifreq *ifr;
575 int i;
577 if (ifname == (char *)NULL) {
578 ifc.ifc_len = sizeof(buff);
579 ifc.ifc_buf = buff;
580 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
581 perror("SIOCGIFCONF failed");
582 return;
583 }
585 ifr = ifc.ifc_req;
586 for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
587 if (if_getconfig(ifr->ifr_name) < 0) {
588 fprintf(stderr,
589 "%s: unknown interface.\n",
590 ifr->ifr_name);
591 continue;
592 }
594 if (((mif_flags & IFF_UP) == 0) && !opt_a) continue;
595 /*ife_print(&ife);*/
596 }
597 } else {
598 if (if_getconfig(ifname) < 0) {
599 fprintf(stderr,
600 "%s: unknown interface.\n", ifname);
601 }
602 }
603 }
605 static int get_drv_info(char *master_ifname)
606 {
607 struct ifreq ifr;
608 struct ethtool_drvinfo info;
609 char *endptr;
611 memset(&ifr, 0, sizeof(ifr));
612 strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
613 ifr.ifr_data = (caddr_t)&info;
615 info.cmd = ETHTOOL_GDRVINFO;
616 strncpy(info.driver, "ifenslave", 32);
617 snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION);
619 if (ioctl(skfd, SIOCETHTOOL, &ifr) < 0) {
620 if (errno == EOPNOTSUPP) {
621 goto out;
622 }
624 saved_errno = errno;
625 v_print("Master '%s': Error: get bonding info failed %s\n",
626 master_ifname, strerror(saved_errno));
627 return 1;
628 }
630 abi_ver = strtoul(info.fw_version, &endptr, 0);
631 if (*endptr) {
632 v_print("Master '%s': Error: got invalid string as an ABI "
633 "version from the bonding module\n",
634 master_ifname);
635 return 1;
636 }
638 out:
639 v_print("ABI ver is %d\n", abi_ver);
641 return 0;
642 }
644 static int change_active(char *master_ifname, char *slave_ifname)
645 {
646 struct ifreq ifr;
647 int res = 0;
649 if (!(slave_flags.ifr_flags & IFF_SLAVE)) {
650 fprintf(stderr,
651 "Illegal operation: The specified slave interface "
652 "'%s' is not a slave\n",
653 slave_ifname);
654 return 1;
655 }
657 strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
658 strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
659 if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &ifr) < 0) &&
660 (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &ifr) < 0)) {
661 saved_errno = errno;
662 v_print("Master '%s': Error: SIOCBONDCHANGEACTIVE failed: "
663 "%s\n",
664 master_ifname, strerror(saved_errno));
665 res = 1;
666 }
668 return res;
669 }
671 static int enslave(char *master_ifname, char *slave_ifname)
672 {
673 struct ifreq ifr;
674 int res = 0;
676 if (slave_flags.ifr_flags & IFF_SLAVE) {
677 fprintf(stderr,
678 "Illegal operation: The specified slave interface "
679 "'%s' is already a slave\n",
680 slave_ifname);
681 return 1;
682 }
684 res = set_if_down(slave_ifname, slave_flags.ifr_flags);
685 if (res) {
686 fprintf(stderr,
687 "Slave '%s': Error: bring interface down failed\n",
688 slave_ifname);
689 return res;
690 }
692 if (abi_ver < 2) {
693 /* Older bonding versions would panic if the slave has no IP
694 * address, so get the IP setting from the master.
695 */
696 set_if_addr(master_ifname, slave_ifname);
697 } else {
698 res = clear_if_addr(slave_ifname);
699 if (res) {
700 fprintf(stderr,
701 "Slave '%s': Error: clear address failed\n",
702 slave_ifname);
703 return res;
704 }
705 }
707 if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) {
708 res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu);
709 if (res) {
710 fprintf(stderr,
711 "Slave '%s': Error: set MTU failed\n",
712 slave_ifname);
713 return res;
714 }
715 }
717 if (hwaddr_set) {
718 /* Master already has an hwaddr
719 * so set it's hwaddr to the slave
720 */
721 if (abi_ver < 1) {
722 /* The driver is using an old ABI, so
723 * the application sets the slave's
724 * hwaddr
725 */
726 res = set_slave_hwaddr(slave_ifname,
727 &(master_hwaddr.ifr_hwaddr));
728 if (res) {
729 fprintf(stderr,
730 "Slave '%s': Error: set hw address "
731 "failed\n",
732 slave_ifname);
733 goto undo_mtu;
734 }
736 /* For old ABI the application needs to bring the
737 * slave back up
738 */
739 res = set_if_up(slave_ifname, slave_flags.ifr_flags);
740 if (res) {
741 fprintf(stderr,
742 "Slave '%s': Error: bring interface "
743 "down failed\n",
744 slave_ifname);
745 goto undo_slave_mac;
746 }
747 }
748 /* The driver is using a new ABI,
749 * so the driver takes care of setting
750 * the slave's hwaddr and bringing
751 * it up again
752 */
753 } else {
754 /* No hwaddr for master yet, so
755 * set the slave's hwaddr to it
756 */
757 if (abi_ver < 1) {
758 /* For old ABI, the master needs to be
759 * down before setting it's hwaddr
760 */
761 res = set_if_down(master_ifname, master_flags.ifr_flags);
762 if (res) {
763 fprintf(stderr,
764 "Master '%s': Error: bring interface "
765 "down failed\n",
766 master_ifname);
767 goto undo_mtu;
768 }
769 }
771 res = set_master_hwaddr(master_ifname,
772 &(slave_hwaddr.ifr_hwaddr));
773 if (res) {
774 fprintf(stderr,
775 "Master '%s': Error: set hw address "
776 "failed\n",
777 master_ifname);
778 goto undo_mtu;
779 }
781 if (abi_ver < 1) {
782 /* For old ABI, bring the master
783 * back up
784 */
785 res = set_if_up(master_ifname, master_flags.ifr_flags);
786 if (res) {
787 fprintf(stderr,
788 "Master '%s': Error: bring interface "
789 "up failed\n",
790 master_ifname);
791 goto undo_master_mac;
792 }
793 }
795 hwaddr_set = 1;
796 }
798 /* Do the real thing */
799 strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
800 strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
801 if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) &&
802 (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) {
803 saved_errno = errno;
804 v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n",
805 master_ifname, strerror(saved_errno));
806 res = 1;
807 }
809 if (res) {
810 goto undo_master_mac;
811 }
813 return 0;
815 /* rollback (best effort) */
816 undo_master_mac:
817 set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr));
818 hwaddr_set = 0;
819 goto undo_mtu;
820 undo_slave_mac:
821 set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr));
822 undo_mtu:
823 set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu);
824 return res;
825 }
827 static int release(char *master_ifname, char *slave_ifname)
828 {
829 struct ifreq ifr;
830 int res = 0;
832 if (!(slave_flags.ifr_flags & IFF_SLAVE)) {
833 fprintf(stderr,
834 "Illegal operation: The specified slave interface "
835 "'%s' is not a slave\n",
836 slave_ifname);
837 return 1;
838 }
840 strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
841 strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
842 if ((ioctl(skfd, SIOCBONDRELEASE, &ifr) < 0) &&
843 (ioctl(skfd, BOND_RELEASE_OLD, &ifr) < 0)) {
844 saved_errno = errno;
845 v_print("Master '%s': Error: SIOCBONDRELEASE failed: %s\n",
846 master_ifname, strerror(saved_errno));
847 return 1;
848 } else if (abi_ver < 1) {
849 /* The driver is using an old ABI, so we'll set the interface
850 * down to avoid any conflicts due to same MAC/IP
851 */
852 res = set_if_down(slave_ifname, slave_flags.ifr_flags);
853 if (res) {
854 fprintf(stderr,
855 "Slave '%s': Error: bring interface "
856 "down failed\n",
857 slave_ifname);
858 }
859 }
861 /* set to default mtu */
862 set_slave_mtu(slave_ifname, 1500);
864 return res;
865 }
867 static int get_if_settings(char *ifname, struct dev_ifr ifra[])
868 {
869 int i;
870 int res = 0;
872 for (i = 0; ifra[i].req_ifr; i++) {
873 strncpy(ifra[i].req_ifr->ifr_name, ifname, IFNAMSIZ);
874 res = ioctl(skfd, ifra[i].req_type, ifra[i].req_ifr);
875 if (res < 0) {
876 saved_errno = errno;
877 v_print("Interface '%s': Error: %s failed: %s\n",
878 ifname, ifra[i].req_name,
879 strerror(saved_errno));
881 return saved_errno;
882 }
883 }
885 return 0;
886 }
888 static int get_slave_flags(char *slave_ifname)
889 {
890 int res = 0;
892 strncpy(slave_flags.ifr_name, slave_ifname, IFNAMSIZ);
893 res = ioctl(skfd, SIOCGIFFLAGS, &slave_flags);
894 if (res < 0) {
895 saved_errno = errno;
896 v_print("Slave '%s': Error: SIOCGIFFLAGS failed: %s\n",
897 slave_ifname, strerror(saved_errno));
898 } else {
899 v_print("Slave %s: flags %04X.\n",
900 slave_ifname, slave_flags.ifr_flags);
901 }
903 return res;
904 }
906 static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr)
907 {
908 unsigned char *addr = (unsigned char *)hwaddr->sa_data;
909 struct ifreq ifr;
910 int res = 0;
912 strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
913 memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr));
914 res = ioctl(skfd, SIOCSIFHWADDR, &ifr);
915 if (res < 0) {
916 saved_errno = errno;
917 v_print("Master '%s': Error: SIOCSIFHWADDR failed: %s\n",
918 master_ifname, strerror(saved_errno));
919 return res;
920 } else {
921 v_print("Master '%s': hardware address set to "
922 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
923 master_ifname, addr[0], addr[1], addr[2],
924 addr[3], addr[4], addr[5]);
925 }
927 return res;
928 }
930 static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr)
931 {
932 unsigned char *addr = (unsigned char *)hwaddr->sa_data;
933 struct ifreq ifr;
934 int res = 0;
936 strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
937 memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr));
938 res = ioctl(skfd, SIOCSIFHWADDR, &ifr);
939 if (res < 0) {
940 saved_errno = errno;
942 v_print("Slave '%s': Error: SIOCSIFHWADDR failed: %s\n",
943 slave_ifname, strerror(saved_errno));
945 if (saved_errno == EBUSY) {
946 v_print(" The device is busy: it must be idle "
947 "before running this command.\n");
948 } else if (saved_errno == EOPNOTSUPP) {
949 v_print(" The device does not support setting "
950 "the MAC address.\n"
951 " Your kernel likely does not support slave "
952 "devices.\n");
953 } else if (saved_errno == EINVAL) {
954 v_print(" The device's address type does not match "
955 "the master's address type.\n");
956 }
957 return res;
958 } else {
959 v_print("Slave '%s': hardware address set to "
960 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
961 slave_ifname, addr[0], addr[1], addr[2],
962 addr[3], addr[4], addr[5]);
963 }
965 return res;
966 }
968 static int set_slave_mtu(char *slave_ifname, int mtu)
969 {
970 struct ifreq ifr;
971 int res = 0;
973 ifr.ifr_mtu = mtu;
974 strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
976 res = ioctl(skfd, SIOCSIFMTU, &ifr);
977 if (res < 0) {
978 saved_errno = errno;
979 v_print("Slave '%s': Error: SIOCSIFMTU failed: %s\n",
980 slave_ifname, strerror(saved_errno));
981 } else {
982 v_print("Slave '%s': MTU set to %d.\n", slave_ifname, mtu);
983 }
985 return res;
986 }
988 static int set_if_flags(char *ifname, short flags)
989 {
990 struct ifreq ifr;
991 int res = 0;
993 ifr.ifr_flags = flags;
994 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
996 res = ioctl(skfd, SIOCSIFFLAGS, &ifr);
997 if (res < 0) {
998 saved_errno = errno;
999 v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n",
1000 ifname, strerror(saved_errno));
1001 } else {
1002 v_print("Interface '%s': flags set to %04X.\n", ifname, flags);
1005 return res;
1008 static int set_if_up(char *ifname, short flags)
1010 return set_if_flags(ifname, flags | IFF_UP);
1013 static int set_if_down(char *ifname, short flags)
1015 return set_if_flags(ifname, flags & ~IFF_UP);
1018 static int clear_if_addr(char *ifname)
1020 struct ifreq ifr;
1021 int res = 0;
1023 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1024 ifr.ifr_addr.sa_family = AF_INET;
1025 memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data));
1027 res = ioctl(skfd, SIOCSIFADDR, &ifr);
1028 if (res < 0) {
1029 saved_errno = errno;
1030 v_print("Interface '%s': Error: SIOCSIFADDR failed: %s\n",
1031 ifname, strerror(saved_errno));
1032 } else {
1033 v_print("Interface '%s': address cleared\n", ifname);
1036 return res;
1039 static int set_if_addr(char *master_ifname, char *slave_ifname)
1041 struct ifreq ifr;
1042 int res;
1043 unsigned char *ipaddr;
1044 int i;
1045 struct {
1046 char *req_name;
1047 char *desc;
1048 int g_ioctl;
1049 int s_ioctl;
1050 } ifra[] = {
1051 {"IFADDR", "addr", SIOCGIFADDR, SIOCSIFADDR},
1052 {"DSTADDR", "destination addr", SIOCGIFDSTADDR, SIOCSIFDSTADDR},
1053 {"BRDADDR", "broadcast addr", SIOCGIFBRDADDR, SIOCSIFBRDADDR},
1054 {"NETMASK", "netmask", SIOCGIFNETMASK, SIOCSIFNETMASK},
1055 {NULL, NULL, 0, 0},
1056 };
1058 for (i = 0; ifra[i].req_name; i++) {
1059 strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
1060 res = ioctl(skfd, ifra[i].g_ioctl, &ifr);
1061 if (res < 0) {
1062 int saved_errno = errno;
1064 v_print("Interface '%s': Error: SIOCG%s failed: %s\n",
1065 master_ifname, ifra[i].req_name,
1066 strerror(saved_errno));
1068 ifr.ifr_addr.sa_family = AF_INET;
1069 memset(ifr.ifr_addr.sa_data, 0,
1070 sizeof(ifr.ifr_addr.sa_data));
1073 strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ);
1074 res = ioctl(skfd, ifra[i].s_ioctl, &ifr);
1075 if (res < 0) {
1076 int saved_errno = errno;
1078 v_print("Interface '%s': Error: SIOCS%s failed: %s\n",
1079 slave_ifname, ifra[i].req_name,
1080 strerror(saved_errno));
1084 ipaddr = ifr.ifr_addr.sa_data;
1085 v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n",
1086 slave_ifname, ifra[i].desc,
1087 ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
1090 return 0;
1093 /*
1094 * Local variables:
1095 * version-control: t
1096 * kept-new-versions: 5
1097 * c-indent-level: 4
1098 * c-basic-offset: 4
1099 * tab-width: 4
1100 * compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave"
1101 * End:
1102 */