@@ -33,6 +33,7 @@
#include "netlink-notifier.h"
#include "netlink-socket.h"
#include "openvswitch/ofpbuf.h"
+#include "lib/sset.h"
#include "ovs-router.h"
#include "packets.h"
#include "rtnetlink.h"
@@ -82,6 +83,7 @@ static struct nln_notifier *route6_notifier = NULL;
static struct nln_notifier *name_notifier = NULL;
static bool route_table_valid = false;
+static struct sset disabled_ifaces = SSET_INITIALIZER(&disabled_ifaces);
static void route_table_reset(void);
static void route_table_handle_msg(const struct route_table_msg *);
@@ -92,6 +94,32 @@ static void route_map_clear(void);
static void name_table_init(void);
static void name_table_change(const struct rtnetlink_change *, void *);
+void
+disable_notify_on_interfaces(const char *ifaces)
+{
+ struct sset tmp_ifaces;
+
+ if (ifaces) {
+ sset_from_delimited_string(&tmp_ifaces, ifaces, ", ");
+ } else {
+ sset_init(&tmp_ifaces);
+ }
+ if (! sset_equals(&disabled_ifaces, &tmp_ifaces)) {
+ const char *iface;
+ struct ds ds = DS_EMPTY_INITIALIZER;
+
+ sset_swap(&disabled_ifaces, &tmp_ifaces);
+ SSET_FOR_EACH (iface, &disabled_ifaces) {
+ ds_put_format(&ds, " %s", iface);
+ }
+ VLOG_DBG_RL(&rl, "route notify disabled interfaces: [%s]",
+ ds_cstr(&ds));
+ ds_destroy(&ds);
+ }
+ sset_destroy(&tmp_ifaces);
+
+}
+
uint64_t
route_table_get_change_seq(void)
{
@@ -358,9 +386,16 @@ static void
route_table_change(const struct route_table_msg *change OVS_UNUSED,
void *aux OVS_UNUSED)
{
- if (!change || change->relevant) {
- route_table_valid = false;
+ if (change) {
+ if (!change->relevant) {
+ return;
+ }
+ if (change->rd.ifname[0] != '\0' &&
+ sset_contains(&disabled_ifaces, change->rd.ifname)) {
+ return;
+ }
}
+ route_table_valid = false;
}
static void
@@ -33,4 +33,5 @@ void route_table_wait(void);
bool route_table_fallback_lookup(const struct in6_addr *ip6_dst,
char name[],
struct in6_addr *gw6);
+void disable_notify_on_interfaces(const char *ifaces);
#endif /* route-table.h */
@@ -128,3 +128,54 @@ OVS_WAIT_UNTIL([test $(ovs-appctl ovs/route/show | grep -c 'p1-route') -eq 0 ])
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+
+
+dnl Checks that disabled interface doesn't trigger route table refresh.
+AT_SETUP([ovs-route - filter by interface])
+AT_KEYWORDS([route])
+OVS_TRAFFIC_VSWITCHD_START()
+
+dnl Create tap port.
+on_exit 'ip link del p1-route; ip link del p2-route'
+AT_CHECK([ip tuntap add name p1-route mode tap])
+AT_CHECK([ip tuntap add name p2-route mode tap])
+AT_CHECK([ip link set p1-route up])
+AT_CHECK([ip link set p2-route up])
+
+dnl Add ip address.
+AT_CHECK([ip addr add 10.0.0.17/24 dev p1-route], [0], [stdout])
+AT_CHECK([ip addr add 10.0.1.17/24 dev p2-route], [0], [stdout])
+
+dnl Check that OVS catches route updates.
+OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -P 'p(1|2)-route' | sort], [dnl
+Cached: 10.0.0.0/24 dev p1-route SRC 10.0.0.17
+Cached: 10.0.0.17/32 dev p1-route SRC 10.0.0.17 local
+Cached: 10.0.1.0/24 dev p2-route SRC 10.0.1.17
+Cached: 10.0.1.17/32 dev p2-route SRC 10.0.1.17 local])
+
+dnl Set disabled interface
+AT_CHECK([ovs-appctl vlog/set 'route_table,dbg'])
+get_log_next_line_num
+AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:route-notify-disabled-interfaces="p2-route"])
+dnl expected log line: "route_table|DBG|route notify disabled interfaces: [ p2-route]"
+OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep -P "notify disabled interfaces: . p2-route"])
+
+dnl Add a route with interface p1-route.
+AT_CHECK([ip route add 10.0.0.18/32 dev p1-route])
+OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep 'p1-route' | sort], [dnl
+Cached: 10.0.0.0/24 dev p1-route SRC 10.0.0.17
+Cached: 10.0.0.17/32 dev p1-route SRC 10.0.0.17 local
+Cached: 10.0.0.18/32 dev p1-route SRC 10.0.0.17])
+
+dnl Add a route with disabled interface p2-route.
+AT_CHECK([ip route add 10.0.1.18/32 dev p2-route])
+dnl Give the main thread a chance to act.
+AT_CHECK([ovs-appctl revalidator/wait])
+dnl Check that OVS didn't refresh route table.
+AT_CHECK([ovs-appctl ovs/route/show | grep 'p2-route' | sort], [0], [dnl
+Cached: 10.0.1.0/24 dev p2-route SRC 10.0.1.17
+Cached: 10.0.1.17/32 dev p2-route SRC 10.0.1.17 local
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
@@ -71,6 +71,7 @@
#include "unixctl.h"
#include "lib/vswitch-idl.h"
#include "vlan-bitmap.h"
+#include "route-table.h"
VLOG_DEFINE_THIS_MODULE(bridge);
@@ -888,6 +889,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
ofproto_set_threads(
smap_get_int(&ovs_cfg->other_config, "n-handler-threads", 0),
smap_get_int(&ovs_cfg->other_config, "n-revalidator-threads", 0));
+ disable_notify_on_interfaces(smap_get(&ovs_cfg->other_config,
+ "route-notify-disabled-interfaces"));
/* Destroy "struct bridge"s, "struct port"s, and "struct iface"s according
* to 'ovs_cfg', with only very minimal configuration otherwise.
@@ -869,6 +869,16 @@
The feature is considered experimental.
</p>
</column>
+ <column name="other_config" key="route-notify-disabled-interfaces">
+ <p>
+ Ignore route changes of specified interfaces. One of the usage
+ scenarios is to prevent kubernets from triggering ovs route table
+ refresh on pod create/destroy.
+ </p>
+ <p>
+ The format is interface names joined by ','. i.e. "eth1,eth2"
+ </p>
+ </column>
</group>
<group title="Status">
<column name="next_cfg">
When ovs host is also a kubernets node, pod creation/deletion may trigger route changes. As a result, ovs run route_table_reset(). As ovs do not care the kubernetes pod routes, route_table_reset() is not neccessary. Signed-off-by: Cheng Li <lic121@chinatelecom.cn> --- lib/route-table.c | 39 +++++++++++++++++++++++++++++++-- lib/route-table.h | 1 + tests/system-route.at | 51 +++++++++++++++++++++++++++++++++++++++++++ vswitchd/bridge.c | 3 +++ vswitchd/vswitch.xml | 10 +++++++++ 5 files changed, 102 insertions(+), 2 deletions(-)