From e83709515598a97e4c6c306ab2952ace13e8a398 Mon Sep 17 00:00:00 2001 From: "Fischer, Anna" Date: Fri, 15 Jan 2010 12:45:08 -0800 Subject: bridge-utils: Add 'hairpin' port forwarding mode This patch adds a 'hairpin' (also called 'reflective relay') mode port configuration to the Linux Ethernet bridge utilities. A bridge supporting hairpin forwarding mode can send frames back out through the port the frame was received on. Hairpin mode is required to support basic VEPA (Virtual Ethernet Port Aggregator) capabilities. You can find additional information on VEPA here: http://tech.groups.yahoo.com/group/evb/ http://www.ieee802.org/1/files/public/docs2009/new-hudson-vepa_seminar-20090514d.pdf http://www.internet2.edu/presentations/jt2009jul/20090719-congdon.pdf (I simplified the code by handling option compatiablity in earlier patch -- Stephen) Signed-off-by: Paul Congdon Signed-off-by: Anna Fischer --- brctl/brctl_cmd.c | 38 ++++++++++++++++++++++++++++++++++++++ brctl/brctl_disp.c | 2 ++ libbridge/libbridge.h | 3 +++ libbridge/libbridge_devif.c | 8 ++++++++ 4 files changed, 51 insertions(+) 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, "\t\tadd bridge" }, { 1, "delbr", br_cmd_delbr, "\t\tdelete bridge" }, @@ -402,6 +438,8 @@ static const struct command commands[] = { " \tadd interface to bridge" }, { 2, "delif", br_cmd_delif, " \tdelete interface from bridge" }, + { 3, "hairpin", br_cmd_hairpin, + " {on|off}\tturn hairpin on/off" }, { 2, "setageing", br_cmd_setageing, "