12#include "nl-default.h"
14#include <netlink/netlink.h>
15#include <netlink/utils.h>
16#include <netlink/route/rtnl.h>
17#include <netlink/route/route.h>
19#include "nexthop-encap.h"
21#include "nl-priv-dynamic-core/nl-core.h"
24#define NH_ATTR_FLAGS 0x000001
25#define NH_ATTR_WEIGHT 0x000002
26#define NH_ATTR_IFINDEX 0x000004
27#define NH_ATTR_GATEWAY 0x000008
28#define NH_ATTR_REALMS 0x000010
29#define NH_ATTR_NEWDST 0x000020
30#define NH_ATTR_VIA 0x000040
31#define NH_ATTR_ENCAP 0x000080
39struct rtnl_nexthop *rtnl_route_nh_alloc(
void)
41 struct rtnl_nexthop *nh;
43 nh = calloc(1,
sizeof(*nh));
47 nl_init_list_head(&nh->rtnh_list);
52struct rtnl_nexthop *rtnl_route_nh_clone(
struct rtnl_nexthop *src)
54 struct rtnl_nexthop *nh;
56 nh = rtnl_route_nh_alloc();
60 nh->rtnh_flags = src->rtnh_flags;
61 nh->rtnh_flag_mask = src->rtnh_flag_mask;
62 nh->rtnh_weight = src->rtnh_weight;
63 nh->rtnh_ifindex = src->rtnh_ifindex;
64 nh->ce_mask = src->ce_mask;
66 if (src->rtnh_gateway) {
68 if (!nh->rtnh_gateway) {
74 if (src->rtnh_newdst) {
76 if (!nh->rtnh_newdst) {
96void rtnl_route_nh_free(
struct rtnl_nexthop *nh)
101 if (nh->rtnh_encap) {
102 if (nh->rtnh_encap->ops && nh->rtnh_encap->ops->destructor)
103 nh->rtnh_encap->ops->destructor(nh->rtnh_encap->priv);
104 free(nh->rtnh_encap->priv);
105 free(nh->rtnh_encap);
112int rtnl_route_nh_compare(
struct rtnl_nexthop *a,
struct rtnl_nexthop *b,
113 uint32_t attrs,
int loose)
117#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
118 diff |= _DIFF(NH_ATTR_IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
119 diff |= _DIFF(NH_ATTR_WEIGHT, a->rtnh_weight != b->rtnh_weight);
120 diff |= _DIFF(NH_ATTR_REALMS, a->rtnh_realms != b->rtnh_realms);
121 diff |= _DIFF(NH_ATTR_GATEWAY,
123 diff |= _DIFF(NH_ATTR_NEWDST,
125 diff |= _DIFF(NH_ATTR_VIA,
nl_addr_cmp(a->rtnh_via, b->rtnh_via));
126 diff |= _DIFF(NH_ATTR_ENCAP,
127 nh_encap_compare(a->rtnh_encap, b->rtnh_encap));
130 diff |= _DIFF(NH_ATTR_FLAGS, (a->rtnh_flags ^ b->rtnh_flags) &
133 diff |= _DIFF(NH_ATTR_FLAGS, a->rtnh_flags != b->rtnh_flags);
150 return !rtnl_route_nh_compare(a, b,
151 NH_ATTR_IFINDEX | NH_ATTR_REALMS |
152 NH_ATTR_GATEWAY | NH_ATTR_NEWDST |
153 NH_ATTR_VIA | NH_ATTR_ENCAP, 0);
156static void nh_dump_line(
struct rtnl_nexthop *nh,
struct nl_dump_params *dp)
158 struct nl_cache *link_cache;
163 if (nh->ce_mask & NH_ATTR_ENCAP)
164 nh_encap_dump(nh->rtnh_encap, dp);
166 if (nh->ce_mask & NH_ATTR_NEWDST)
172 if (nh->ce_mask & NH_ATTR_VIA)
176 if (nh->ce_mask & NH_ATTR_GATEWAY)
180 if(nh->ce_mask & NH_ATTR_IFINDEX) {
187 nl_dump(dp,
" dev %d", nh->rtnh_ifindex);
193 nl_cache_put(link_cache);
196static void nh_dump_details(
struct rtnl_nexthop *nh,
struct nl_dump_params *dp)
198 struct nl_cache *link_cache;
205 if (nh->ce_mask & NH_ATTR_ENCAP)
206 nh_encap_dump(nh->rtnh_encap, dp);
208 if (nh->ce_mask & NH_ATTR_NEWDST)
212 if (nh->ce_mask & NH_ATTR_VIA)
216 if (nh->ce_mask & NH_ATTR_GATEWAY)
220 if(nh->ce_mask & NH_ATTR_IFINDEX) {
227 nl_dump(dp,
" dev %d", nh->rtnh_ifindex);
230 if (nh->ce_mask & NH_ATTR_WEIGHT)
231 nl_dump(dp,
" weight %u", nh->rtnh_weight);
233 if (nh->ce_mask & NH_ATTR_REALMS)
234 nl_dump(dp,
" realm %04x:%04x",
238 if (nh->ce_mask & NH_ATTR_FLAGS)
239 nl_dump(dp,
" <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags,
243 nl_cache_put(link_cache);
246void rtnl_route_nh_dump(
struct rtnl_nexthop *nh,
struct nl_dump_params *dp)
250 nh_dump_line(nh, dp);
255 if (dp->
dp_ivar == NH_DUMP_FROM_DETAILS)
256 nh_dump_details(nh, dp);
264void nh_set_encap(
struct rtnl_nexthop *nh,
struct rtnl_nh_encap *rtnh_encap)
266 if (nh->rtnh_encap) {
267 if (nh->rtnh_encap->ops && nh->rtnh_encap->ops->destructor)
268 nh->rtnh_encap->ops->destructor(nh->rtnh_encap->priv);
269 free(nh->rtnh_encap->priv);
270 free(nh->rtnh_encap);
274 nh->rtnh_encap = rtnh_encap;
275 nh->ce_mask |= NH_ATTR_ENCAP;
277 nh->rtnh_encap = NULL;
278 nh->ce_mask &= ~NH_ATTR_ENCAP;
287void rtnl_route_nh_set_weight(
struct rtnl_nexthop *nh, uint8_t weight)
289 nh->rtnh_weight = weight;
290 nh->ce_mask |= NH_ATTR_WEIGHT;
293uint8_t rtnl_route_nh_get_weight(
struct rtnl_nexthop *nh)
295 return nh->rtnh_weight;
298void rtnl_route_nh_set_ifindex(
struct rtnl_nexthop *nh,
int ifindex)
300 nh->rtnh_ifindex = ifindex;
301 nh->ce_mask |= NH_ATTR_IFINDEX;
304int rtnl_route_nh_get_ifindex(
struct rtnl_nexthop *nh)
306 return nh->rtnh_ifindex;
310void rtnl_route_nh_set_gateway(
struct rtnl_nexthop *nh,
struct nl_addr *addr)
312 struct nl_addr *old = nh->rtnh_gateway;
316 nh->ce_mask |= NH_ATTR_GATEWAY;
318 nh->ce_mask &= ~NH_ATTR_GATEWAY;
319 nh->rtnh_gateway = NULL;
326struct nl_addr *rtnl_route_nh_get_gateway(
struct rtnl_nexthop *nh)
328 return nh->rtnh_gateway;
331void rtnl_route_nh_set_flags(
struct rtnl_nexthop *nh,
unsigned int flags)
333 nh->rtnh_flag_mask |= flags;
334 nh->rtnh_flags |= flags;
335 nh->ce_mask |= NH_ATTR_FLAGS;
338void rtnl_route_nh_unset_flags(
struct rtnl_nexthop *nh,
unsigned int flags)
340 nh->rtnh_flag_mask |= flags;
341 nh->rtnh_flags &= ~flags;
342 nh->ce_mask |= NH_ATTR_FLAGS;
345unsigned int rtnl_route_nh_get_flags(
struct rtnl_nexthop *nh)
347 return nh->rtnh_flags;
350void rtnl_route_nh_set_realms(
struct rtnl_nexthop *nh, uint32_t realms)
352 nh->rtnh_realms = realms;
353 nh->ce_mask |= NH_ATTR_REALMS;
356uint32_t rtnl_route_nh_get_realms(
struct rtnl_nexthop *nh)
358 return nh->rtnh_realms;
361int rtnl_route_nh_set_newdst(
struct rtnl_nexthop *nh,
struct nl_addr *addr)
363 struct nl_addr *old = nh->rtnh_newdst;
367 nh->ce_mask |= NH_ATTR_NEWDST;
369 nh->ce_mask &= ~NH_ATTR_NEWDST;
370 nh->rtnh_newdst = NULL;
379struct nl_addr *rtnl_route_nh_get_newdst(
struct rtnl_nexthop *nh)
381 return nh->rtnh_newdst;
384int rtnl_route_nh_set_via(
struct rtnl_nexthop *nh,
struct nl_addr *addr)
386 struct nl_addr *old = nh->rtnh_via;
390 nh->ce_mask |= NH_ATTR_VIA;
392 nh->ce_mask &= ~NH_ATTR_VIA;
402struct nl_addr *rtnl_route_nh_get_via(
struct rtnl_nexthop *nh)
414static const struct trans_tbl nh_flags[] = {
415 __ADD(RTNH_F_DEAD, dead),
416 __ADD(RTNH_F_PERVASIVE, pervasive),
417 __ADD(RTNH_F_ONLINK, onlink),
420char *rtnl_route_nh_flags2str(
int flags,
char *buf,
size_t len)
422 return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
425int rtnl_route_nh_str2flags(
const char *name)
427 return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
struct nl_cache * nl_cache_mngt_require_safe(const char *name)
Return cache previously provided via nl_cache_mngt_provide()
char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len)
Translate interface index to corresponding link name.
int rtnl_route_nh_identical(struct rtnl_nexthop *a, struct rtnl_nexthop *b)
Check if the fixed attributes of two nexthops are identical, and may only differ in flags or weight.
#define RTNL_REALM_TO(realm)
Extract TO realm from a realms field.
#define RTNL_REALM_FROM(realm)
Extract FROM realm from a realms field.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ NL_DUMP_STATS
Dump all attributes including statistics.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
enum nl_dump_type dp_type
Specifies the type of dump that is requested.
int dp_ivar
PRIVATE Owned by the current caller.