diff options
-rw-r--r-- | brctl/brctl_cmd.c | 38 | ||||
-rw-r--r-- | brctl/brctl_disp.c | 2 | ||||
-rw-r--r-- | libbridge/libbridge.h | 3 | ||||
-rw-r--r-- | libbridge/libbridge_devif.c | 8 |
4 files changed, 51 insertions, 0 deletions
diff --git a/brctl/brctl_cmd.c b/brctl/brctl_cmd.c index c93dd55..d37e99c 100644 --- a/brctl/brctl_cmd.c +++ b/brctl/brctl_cmd.c @@ -395,6 +395,42 @@ static int br_cmd_showmacs(int argc, char *const* argv) return 0; } +static int br_cmd_hairpin(int argc, char *const* argv) +{ + int hairpin, err; + const char *brname = *++argv; + const char *ifname = *++argv; + const char *hpmode = *++argv; + + if (!strcmp(hpmode, "on") || !strcmp(hpmode, "yes") + || !strcmp(hpmode, "1")) + hairpin = 1; + else if (!strcmp(hpmode, "off") || !strcmp(hpmode, "no") + || !strcmp(hpmode, "0")) + hairpin = 0; + else { + fprintf(stderr, "expect on/off for argument\n"); + return 1; + } + if (if_nametoindex(ifname) == 0) { + fprintf(stderr, "interface %s does not exist!\n", + ifname); + return 1; + } else if (if_nametoindex(brname) == 0) { + fprintf(stderr, "bridge %s does not exist!\n", + brname); + return 1; + } + + err = br_set_hairpin_mode(brname, ifname, hairpin); + + if (err) { + fprintf(stderr, "can't set %s to hairpin on bridge %s: %s\n", + ifname, brname, strerror(err)); + } + return err != 0; +} + static const struct command commands[] = { { 1, "addbr", br_cmd_addbr, "<bridge>\t\tadd bridge" }, { 1, "delbr", br_cmd_delbr, "<bridge>\t\tdelete bridge" }, @@ -402,6 +438,8 @@ static const struct command commands[] = { "<bridge> <device>\tadd interface to bridge" }, { 2, "delif", br_cmd_delif, "<bridge> <device>\tdelete interface from bridge" }, + { 3, "hairpin", br_cmd_hairpin, + "<bridge> <port> {on|off}\tturn hairpin on/off" }, { 2, "setageing", br_cmd_setageing, "<bridge> <time>\t\tset ageing time" }, { 2, "setbridgeprio", br_cmd_setbridgeprio, diff --git a/brctl/brctl_disp.c b/brctl/brctl_disp.c index 27ce6d2..3e81241 100644 --- a/brctl/brctl_disp.c +++ b/brctl/brctl_disp.c @@ -93,6 +93,8 @@ static int dump_port_info(const char *br, const char *p, void *arg) printf("CONFIG_PENDING "); if (pinfo.top_change_ack) printf("TOPOLOGY_CHANGE_ACK "); + if (pinfo.hairpin_mode) + printf("\n hairpin mode\t\t\%4i", pinfo.hairpin_mode); printf("\n"); printf("\n"); return 0; diff --git a/libbridge/libbridge.h b/libbridge/libbridge.h index 016acea..39964f2 100644 --- a/libbridge/libbridge.h +++ b/libbridge/libbridge.h @@ -80,6 +80,7 @@ struct port_info struct timeval message_age_timer_value; struct timeval forward_delay_timer_value; struct timeval hold_timer_value; + unsigned char hairpin_mode; }; extern int br_init(void); @@ -113,4 +114,6 @@ extern int br_set_path_cost(const char *br, const char *p, int path_cost); extern int br_read_fdb(const char *br, struct fdb_entry *fdbs, unsigned long skip, int num); +extern int br_set_hairpin_mode(const char *bridge, const char *dev, + int hairpin_mode); #endif diff --git a/libbridge/libbridge_devif.c b/libbridge/libbridge_devif.c index 3a4868c..aa8bc36 100644 --- a/libbridge/libbridge_devif.c +++ b/libbridge/libbridge_devif.c @@ -238,6 +238,7 @@ static int old_get_port_info(const char *brname, const char *port, __jiffies_to_tv(&info->forward_delay_timer_value, i.forward_delay_timer_value); __jiffies_to_tv(&info->hold_timer_value, i.hold_timer_value); + info->hairpin_mode = 0; return 0; } @@ -270,6 +271,8 @@ int br_get_port_info(const char *brname, const char *port, fetch_tv(path, "message_age_timer", &info->message_age_timer_value); fetch_tv(path, "forward_delay_timer", &info->forward_delay_timer_value); fetch_tv(path, "hold_timer", &info->hold_timer_value); + info->hairpin_mode = fetch_int(path, "hairpin_mode"); + closedir(d); return 0; @@ -380,6 +383,11 @@ int br_set_path_cost(const char *bridge, const char *port, int cost) return port_set(bridge, port, "path_cost", cost, BRCTL_SET_PATH_COST); } +int br_set_hairpin_mode(const char *bridge, const char *port, int hairpin_mode) +{ + return port_set(bridge, port, "hairpin_mode", hairpin_mode, 0); +} + static inline void __copy_fdb(struct fdb_entry *ent, const struct __fdb_entry *f) { |