Skip to content

Commit b871a8e

Browse files
committed
[nh-encap] Support cloning rtnl_nh_encap in rtnl_route_nh_clone
Signed-off-by: Christoph Paasch <[email protected]>
1 parent b5712e5 commit b871a8e

File tree

7 files changed

+65
-15
lines changed

7 files changed

+65
-15
lines changed

include/netlink/route/nexthop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ extern int rtnl_route_nh_str2flags(const char *);
6262
*/
6363
extern struct rtnl_nh_encap *rtnl_nh_encap_alloc(void);
6464
extern void rtnl_nh_encap_free(struct rtnl_nh_encap *nh_encap);
65+
struct rtnl_nh_encap *rtnl_nh_encap_clone(struct rtnl_nh_encap *src);
6566

6667
extern int rtnl_nh_encap_mpls(struct rtnl_nh_encap *nh_encap,
6768
struct nl_addr *dst, uint8_t ttl);

lib/route/nexthop-encap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ struct nh_encap_ops {
88
int (*parse_msg)(struct nlattr *nla, struct rtnl_nexthop *rtnh);
99

1010
int (*compare)(void *a, void *b);
11+
void *(*clone)(void *priv);
1112

1213
void (*dump)(void *priv, struct nl_dump_params *dp);
1314
void (*destructor)(void *priv);

lib/route/nexthop.c

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
#include <netlink/route/route.h>
1818

1919
#include "nexthop-encap.h"
20-
#include "nl-route.h"
20+
#include "nl-aux-route/nl-route.h"
2121
#include "nl-priv-dynamic-core/nl-core.h"
22+
#include "nl-route.h"
2223

2324
/** @cond SKIP */
2425
#define NH_ATTR_FLAGS 0x000001
@@ -51,7 +52,7 @@ struct rtnl_nexthop *rtnl_route_nh_alloc(void)
5152

5253
struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src)
5354
{
54-
struct rtnl_nexthop *nh;
55+
_nl_auto_rtnl_nexthop struct rtnl_nexthop *nh = NULL;
5556

5657
nh = rtnl_route_nh_alloc();
5758
if (!nh)
@@ -66,32 +67,30 @@ struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src)
6667

6768
if (src->rtnh_gateway) {
6869
nh->rtnh_gateway = nl_addr_clone(src->rtnh_gateway);
69-
if (!nh->rtnh_gateway) {
70-
free(nh);
70+
if (!nh->rtnh_gateway)
7171
return NULL;
72-
}
7372
}
7473

7574
if (src->rtnh_newdst) {
7675
nh->rtnh_newdst = nl_addr_clone(src->rtnh_newdst);
77-
if (!nh->rtnh_newdst) {
78-
nl_addr_put(nh->rtnh_gateway);
79-
free(nh);
76+
if (!nh->rtnh_newdst)
8077
return NULL;
81-
}
8278
}
8379

8480
if (src->rtnh_via) {
8581
nh->rtnh_via = nl_addr_clone(src->rtnh_via);
86-
if (!nh->rtnh_via) {
87-
nl_addr_put(nh->rtnh_gateway);
88-
nl_addr_put(nh->rtnh_newdst);
89-
free(nh);
82+
if (!nh->rtnh_via)
9083
return NULL;
91-
}
9284
}
9385

94-
return nh;
86+
/* Clone encapsulation information if present */
87+
if (src->rtnh_encap) {
88+
nh->rtnh_encap = rtnl_nh_encap_clone(src->rtnh_encap);
89+
if (!nh->rtnh_encap)
90+
return NULL;
91+
}
92+
93+
return _nl_steal_pointer(&nh);
9594
}
9695

9796
void rtnl_route_nh_free(struct rtnl_nexthop *nh)

lib/route/nh.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,29 @@ void rtnl_nh_encap_free(struct rtnl_nh_encap *nh_encap)
669669
free(nh_encap);
670670
}
671671

672+
struct rtnl_nh_encap *rtnl_nh_encap_clone(struct rtnl_nh_encap *src)
673+
{
674+
struct rtnl_nh_encap *new_encap;
675+
676+
if (!src)
677+
return NULL;
678+
679+
new_encap = rtnl_nh_encap_alloc();
680+
if (!new_encap)
681+
return NULL;
682+
683+
new_encap->ops = src->ops;
684+
if (new_encap->ops) {
685+
new_encap->priv = new_encap->ops->clone(src->priv);
686+
if (!new_encap->priv) {
687+
rtnl_nh_encap_free(new_encap);
688+
return NULL;
689+
}
690+
}
691+
692+
return new_encap;
693+
}
694+
672695
/*
673696
* Retrieve the encapsulation associated with a nexthop if any.
674697
*/

lib/route/nh_encap_mpls.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct nh_encap_ops mpls_encap_ops = {
108108
.build_msg = mpls_encap_build_msg,
109109
.parse_msg = mpls_encap_parse_msg,
110110
.compare = mpls_encap_compare,
111+
.clone = mpls_encap_clone,
111112
.dump = mpls_encap_dump,
112113
.destructor = mpls_encap_destructor,
113114
};

libnl-route-3.sym

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,7 @@ global:
13721372
rtnl_link_is_bond;
13731373
rtnl_nh_add;
13741374
rtnl_nh_encap_alloc;
1375+
rtnl_nh_encap_clone;
13751376
rtnl_nh_encap_free;
13761377
rtnl_nh_encap_mpls;
13771378
rtnl_nh_get_encap_mpls_dst;

tests/cksuite-route-nexthop.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ START_TEST(test_route_nexthop_api_set_get_all)
3636
_nl_auto_nl_addr struct nl_addr *via6 = NULL;
3737
_nl_auto_nl_addr struct nl_addr *mpls = NULL;
3838
_nl_auto_rtnl_nexthop struct rtnl_nexthop *clone = NULL;
39+
_nl_auto_rtnl_nexthop struct rtnl_nexthop *clone_with_encap = NULL;
3940
struct rtnl_nh_encap *encap = NULL;
4041
struct rtnl_nh_encap *got = NULL;
42+
struct rtnl_nh_encap *encap_clone = NULL;
4143
uint32_t realms = 0xAABBCCDDu;
4244
char flags_buf[64];
4345
int flags_parsed;
@@ -141,6 +143,28 @@ START_TEST(test_route_nexthop_api_set_get_all)
141143
ck_assert_ptr_nonnull(rtnl_nh_get_encap_mpls_dst(got));
142144
ck_assert_int_eq(rtnl_nh_get_encap_mpls_ttl(got), 64);
143145

146+
/* Exercise rtnl_nh_encap_clone() directly */
147+
encap_clone = rtnl_nh_encap_clone(encap);
148+
ck_assert_ptr_nonnull(encap_clone);
149+
ck_assert_ptr_nonnull(rtnl_nh_get_encap_mpls_dst(encap_clone));
150+
ck_assert_int_eq(
151+
nl_addr_cmp(rtnl_nh_get_encap_mpls_dst(encap_clone), mpls), 0);
152+
ck_assert_uint_eq(rtnl_nh_get_encap_mpls_ttl(encap_clone), 64);
153+
/* Free the cloned encap explicitly */
154+
rtnl_nh_encap_free(encap_clone);
155+
encap_clone = NULL;
156+
157+
/* Exercise nexthop clone with encap: encap should be deep-cloned */
158+
clone_with_encap = rtnl_route_nh_clone(nh);
159+
ck_assert_ptr_nonnull(clone_with_encap);
160+
encap_clone = rtnl_route_nh_get_encap(clone_with_encap);
161+
ck_assert_ptr_nonnull(encap_clone);
162+
/* The encap on the clone must not be the same pointer */
163+
ck_assert_ptr_ne(encap_clone, encap);
164+
ck_assert_int_eq(
165+
nl_addr_cmp(rtnl_nh_get_encap_mpls_dst(encap_clone), mpls), 0);
166+
ck_assert_uint_eq(rtnl_nh_get_encap_mpls_ttl(encap_clone), 64);
167+
144168
/* Clear encap and verify it is removed */
145169
ck_assert_int_eq(rtnl_route_nh_set_encap(nh, NULL), 0);
146170
ck_assert_ptr_eq(rtnl_route_nh_get_encap(nh), NULL);

0 commit comments

Comments
 (0)