diff -Nur a/bridge.c netifd-2019-08-05-5e02f944/bridge.c --- a/bridge.c 2020-05-01 16:39:45.875448393 -0700 +++ netifd-2019-08-05-5e02f944/bridge.c 2020-05-01 16:43:05.086378758 -0700 @@ -34,6 +34,7 @@ BRIDGE_ATTR_BRIDGE_EMPTY, BRIDGE_ATTR_MULTICAST_QUERIER, BRIDGE_ATTR_HASH_MAX, + BRIDGE_ATTR_HAIRPIN, BRIDGE_ATTR_ROBUSTNESS, BRIDGE_ATTR_QUERY_INTERVAL, BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL, @@ -53,6 +54,7 @@ [BRIDGE_ATTR_BRIDGE_EMPTY] = { "bridge_empty", BLOBMSG_TYPE_BOOL }, [BRIDGE_ATTR_MULTICAST_QUERIER] = { "multicast_querier", BLOBMSG_TYPE_BOOL }, [BRIDGE_ATTR_HASH_MAX] = { "hash_max", BLOBMSG_TYPE_INT32 }, + [BRIDGE_ATTR_HAIRPIN] = { "hairpin", BLOBMSG_TYPE_BOOL }, [BRIDGE_ATTR_ROBUSTNESS] = { "robustness", BLOBMSG_TYPE_INT32 }, [BRIDGE_ATTR_QUERY_INTERVAL] = { "query_interval", BLOBMSG_TYPE_INT32 }, [BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL] = { "query_response_interval", BLOBMSG_TYPE_INT32 }, @@ -219,6 +221,7 @@ } device_set_present(&bst->dev, true); + system_bridge_set_hairpin(bm->dev.dev, bst->config.hairpin); device_broadcast_event(&bst->dev, DEV_EVENT_TOPO_CHANGE); return 0; @@ -577,6 +580,7 @@ cfg->hash_max = 512; cfg->bridge_empty = false; cfg->priority = 0x7FFF; + cfg->hairpin = false; if ((cur = tb[BRIDGE_ATTR_STP])) cfg->stp = blobmsg_get_bool(cur); @@ -633,6 +637,10 @@ if ((cur = tb[BRIDGE_ATTR_BRIDGE_EMPTY])) cfg->bridge_empty = blobmsg_get_bool(cur); + + if ((cur = tb[BRIDGE_ATTR_HAIRPIN])) + cfg->hairpin = blobmsg_get_bool(cur); + } static enum dev_change_type diff -Nur a/system.h netifd-2019-08-05-5e02f944/system.h --- a/system.h 2020-05-01 16:39:45.879448372 -0700 +++ netifd-2019-08-05-5e02f944/system.h 2020-05-01 16:40:35.427182113 -0700 @@ -126,6 +126,7 @@ int hello_time; int max_age; int hash_max; + int hairpin; }; struct bonding_config { @@ -190,6 +191,7 @@ int system_bridge_delbr(struct device *bridge); int system_bridge_addif(struct device *bridge, struct device *dev); int system_bridge_delif(struct device *bridge, struct device *dev); +void system_bridge_set_hairpin(struct device *dev, int enable); int system_bonding_addbonding(struct device *bonding, struct bonding_config *cfg); int system_bonding_delbonding(struct device *bonding); diff -Nur a/system-linux.c netifd-2019-08-05-5e02f944/system-linux.c --- a/system-linux.c 2020-05-01 16:39:45.879448372 -0700 +++ netifd-2019-08-05-5e02f944/system-linux.c 2020-05-01 16:40:35.423182135 -0700 @@ -910,6 +910,13 @@ return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL); } +void system_bridge_set_hairpin(struct device *dev, int enable) +{ + char mode[4]; + snprintf(mode, sizeof(mode), "%d", !!enable); + system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, mode); +} + int system_if_resolve(struct device *dev) { struct ifreq ifr;