Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108989501
D36075.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D36075.diff
View Options
diff --git a/sys/net/route/nhop.h b/sys/net/route/nhop.h
--- a/sys/net/route/nhop.h
+++ b/sys/net/route/nhop.h
@@ -206,6 +206,7 @@
int nhop_get_upper_family(const struct nhop_object *nh);
int nhop_get_neigh_family(const struct nhop_object *nh);
uint32_t nhop_get_fibnum(const struct nhop_object *nh);
+void nhop_set_fibnum(struct nhop_object *nh, uint32_t fibnum);
uint32_t nhop_get_expire(const struct nhop_object *nh);
void nhop_set_expire(struct nhop_object *nh, uint32_t expire);
diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c
--- a/sys/net/route/nhop_ctl.c
+++ b/sys/net/route/nhop_ctl.c
@@ -312,14 +312,20 @@
*/
struct nhop_object *
nhop_get_nhop(struct nhop_object *nh, int *perror)
+{
+ struct rib_head *rnh = nhop_get_rh(nh);
+
+ return (nhop_get_nhop_internal(rnh, nh, perror));
+}
+
+struct nhop_object *
+nhop_get_nhop_internal(struct rib_head *rnh, struct nhop_object *nh, int *perror)
{
struct nhop_priv *tmp_priv;
int error;
nh->nh_aifp = get_aifp(nh);
- struct rib_head *rnh = nhop_get_rh(nh);
-
/* Give the protocols chance to augment nexthop properties */
error = rnh->rnh_augment_nh(rnh->rib_fibnum, nh);
if (error != 0) {
@@ -893,6 +899,12 @@
return (nh->nh_priv->nh_fibnum);
}
+void
+nhop_set_fibnum(struct nhop_object *nh, uint32_t fibnum)
+{
+ nh->nh_priv->nh_fibnum = fibnum;
+}
+
uint32_t
nhop_get_expire(const struct nhop_object *nh)
{
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -596,6 +596,71 @@
return (0);
}
+/*
+ * Tries to copy route @rt from one rtable to the rtable specified by @dst_rh.
+ * @rt: route to copy.
+ * @rnd_src: nhop and weight. Multipath routes are not supported
+ * @rh_dst: target rtable.
+ * @rc: operation result storage
+ *
+ * Return 0 on success.
+ */
+int
+rib_copy_route(struct rtentry *rt, const struct route_nhop_data *rnd_src,
+ struct rib_head *rh_dst, struct rib_cmd_info *rc)
+{
+ struct nhop_object *nh_src = rnd_src->rnd_nhop;
+ int error;
+
+ MPASS((nh_src->nh_flags & NHF_MULTIPATH) == 0);
+
+#if DEBUG_MAX_LEVEL >= LOG_DEBUG2
+ char nhbuf[NHOP_PRINT_BUFSIZE], rtbuf[NHOP_PRINT_BUFSIZE];
+ nhop_print_buf_any(nh_src, nhbuf, sizeof(nhbuf));
+ rt_print_buf(rt, rtbuf, sizeof(rtbuf));
+ FIB_RH_LOG(LOG_DEBUG2, rh_dst, "copying %s -> %s from fib %u",
+ rtbuf, nhbuf, nhop_get_fibnum(nh_src));
+#endif
+ struct nhop_object *nh = nhop_alloc(rh_dst->rib_fibnum, rh_dst->rib_family);
+ if (nh == NULL) {
+ FIB_RH_LOG(LOG_INFO, rh_dst, "unable to allocate new nexthop");
+ return (ENOMEM);
+ }
+ nhop_copy(nh, rnd_src->rnd_nhop);
+ nhop_set_fibnum(nh, rh_dst->rib_fibnum);
+ nh = nhop_get_nhop_internal(rh_dst, nh, &error);
+ if (error != 0) {
+ FIB_RH_LOG(LOG_INFO, rh_dst,
+ "unable to finalize new nexthop: error %d", error);
+ return (ENOMEM);
+ }
+
+ struct rtentry *rt_new = rt_alloc(rh_dst, rt_key(rt), rt_mask(rt));
+ if (rt_new == NULL) {
+ FIB_RH_LOG(LOG_INFO, rh_dst, "unable to create new rtentry");
+ nhop_free(nh);
+ return (ENOMEM);
+ }
+
+ struct route_nhop_data rnd = {
+ .rnd_nhop = nh,
+ .rnd_weight = rnd_src->rnd_weight
+ };
+ int op_flags = RTM_F_CREATE | (NH_IS_PINNED(nh) ? RTM_F_FORCE : 0);
+ error = add_route_flags(rh_dst, rt_new, &rnd, op_flags, rc);
+
+ if (error != 0) {
+#if DEBUG_MAX_LEVEL >= LOG_DEBUG
+ char buf[NHOP_PRINT_BUFSIZE];
+ rt_print_buf(rt_new, buf, sizeof(buf));
+ FIB_RH_LOG(LOG_DEBUG, rh_dst, "Unable to add route %s: error %d", buf, error);
+#endif
+ nhop_free(nh);
+ rt_free_immediate(rt_new);
+ }
+ return (error);
+}
+
/*
* Adds route defined by @info into the kernel table specified by @fibnum and
* sa_family in @info->rti_info[RTAX_DST].
diff --git a/sys/net/route/route_ifaddrs.c b/sys/net/route/route_ifaddrs.c
--- a/sys/net/route/route_ifaddrs.c
+++ b/sys/net/route/route_ifaddrs.c
@@ -195,4 +195,49 @@
return (ifa_maintain_loopback_route(RTM_CHANGE, "switch", ifa, ia));
}
+static bool
+match_kernel_route(const struct rtentry *rt, struct nhop_object *nh)
+{
+ if (!NH_IS_NHGRP(nh) && (nhop_get_rtflags(nh) & RTF_PINNED) &&
+ nh->nh_aifp->if_fib == nhop_get_fibnum(nh))
+ return (true);
+ return (false);
+}
+
+static int
+pick_kernel_route(struct rtentry *rt, void *arg)
+{
+ struct nhop_object *nh = rt->rt_nhop;
+ struct rib_head *rh_dst = (struct rib_head *)arg;
+
+ if (match_kernel_route(rt, nh)) {
+ struct rib_cmd_info rc = {};
+ struct route_nhop_data rnd = {
+ .rnd_nhop = nh,
+ .rnd_weight = rt->rt_weight,
+ };
+ rib_copy_route(rt, &rnd, rh_dst, &rc);
+ }
+ return (0);
+}
+
+/*
+ * Tries to copy kernel routes matching pattern from @rh_src to @rh_dst.
+ *
+ * Note: as this function acquires locks for both @rh_src and @rh_dst,
+ * it needs to be called under RTABLES_LOCK() to avoid deadlocking
+ * with multiple ribs.
+ */
+void
+rib_copy_kernel_routes(struct rib_head *rh_src, struct rib_head *rh_dst)
+{
+ struct epoch_tracker et;
+
+ if (V_rt_add_addr_allfibs == 0)
+ return;
+
+ NET_EPOCH_ENTER(et);
+ rib_walk_ext_internal(rh_src, false, pick_kernel_route, NULL, rh_dst);
+ NET_EPOCH_EXIT(et);
+}
diff --git a/sys/net/route/route_tables.c b/sys/net/route/route_tables.c
--- a/sys/net/route/route_tables.c
+++ b/sys/net/route/route_tables.c
@@ -162,6 +162,20 @@
return (error);
}
+/*
+ * If required, copy interface routes from existing tables to the
+ * newly-created routing table.
+ */
+static void
+populate_kernel_routes(struct rib_head **new_rt_tables, struct rib_head *rh)
+{
+ for (int i = 0; i < V_rt_numfibs; i++) {
+ struct rib_head *rh_src = new_rt_tables[i * (AF_MAX + 1) + rh->rib_family];
+ if ((rh_src != NULL) && (rh_src != rh))
+ rib_copy_kernel_routes(rh_src, rh);
+ }
+}
+
/*
* Grows up the number of routing tables in the current fib.
* Function creates new index array for all rtables and allocates
@@ -214,6 +228,8 @@
if (rh == NULL)
log(LOG_ERR, "unable to create routing table for %d.%d\n",
dom->dom_family, i);
+ else
+ populate_kernel_routes(new_rt_tables, rh);
*prnh = rh;
}
}
diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h
--- a/sys/net/route/route_var.h
+++ b/sys/net/route/route_var.h
@@ -78,7 +78,7 @@
};
#define RIB_RLOCK_TRACKER struct rm_priotracker _rib_tracker
-#define RIB_LOCK_INIT(rh) rm_init(&(rh)->rib_lock, "rib head lock")
+#define RIB_LOCK_INIT(rh) rm_init_flags(&(rh)->rib_lock, "rib head lock", RM_DUPOK)
#define RIB_LOCK_DESTROY(rh) rm_destroy(&(rh)->rib_lock)
#define RIB_RLOCK(rh) rm_rlock(&(rh)->rib_lock, &_rib_tracker)
#define RIB_RUNLOCK(rh) rm_runlock(&(rh)->rib_lock, &_rib_tracker)
@@ -221,6 +221,8 @@
const struct rt_addrinfo *info, struct route_nhop_data *rnd);
struct rtentry *lookup_prefix_rt(struct rib_head *rnh, const struct rtentry *rt,
struct route_nhop_data *rnd);
+int rib_copy_route(struct rtentry *rt, const struct route_nhop_data *rnd_src,
+ struct rib_head *rh_dst, struct rib_cmd_info *rc);
bool nhop_can_multipath(const struct nhop_object *nh);
bool match_nhop_gw(const struct nhop_object *nh, const struct sockaddr *gw);
@@ -239,6 +241,9 @@
void rib_init_subscriptions(struct rib_head *rnh);
void rib_destroy_subscriptions(struct rib_head *rnh);
+/* route_ifaddrs.c */
+void rib_copy_kernel_routes(struct rib_head *rh_src, struct rib_head *rh_dst);
+
/* Nexhops */
void nhops_init(void);
int nhops_init_rib(struct rib_head *rh);
@@ -247,6 +252,8 @@
int nhop_try_ref_object(struct nhop_object *nh);
void nhop_ref_any(struct nhop_object *nh);
void nhop_free_any(struct nhop_object *nh);
+struct nhop_object *nhop_get_nhop_internal(struct rib_head *rnh,
+ struct nhop_object *nh, int *perror);
int nhop_create_from_info(struct rib_head *rnh, struct rt_addrinfo *info,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 31, 8:42 AM (8 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16358999
Default Alt Text
D36075.diff (7 KB)
Attached To
Mode
D36075: routing: populate fibs with interface routes after growing net.fibs.
Attached
Detach File
Event Timeline
Log In to Comment