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"
20#include "nl-aux-route/nl-route.h"
21#include "nl-priv-dynamic-core/nl-core.h"
25#define NH_ATTR_FLAGS 0x000001
26#define NH_ATTR_WEIGHT 0x000002
27#define NH_ATTR_IFINDEX 0x000004
28#define NH_ATTR_GATEWAY 0x000008
29#define NH_ATTR_REALMS 0x000010
30#define NH_ATTR_NEWDST 0x000020
31#define NH_ATTR_VIA 0x000040
32#define NH_ATTR_ENCAP 0x000080
40struct rtnl_nexthop *rtnl_route_nh_alloc(
void)
42 struct rtnl_nexthop *nh;
44 nh = calloc(1,
sizeof(*nh));
48 nl_init_list_head(&nh->rtnh_list);
53struct rtnl_nexthop *rtnl_route_nh_clone(
struct rtnl_nexthop *src)
55 _nl_auto_rtnl_nexthop
struct rtnl_nexthop *nh = NULL;
57 nh = rtnl_route_nh_alloc();
61 nh->rtnh_flags = src->rtnh_flags;
62 nh->rtnh_flag_mask = src->rtnh_flag_mask;
63 nh->rtnh_weight = src->rtnh_weight;
64 nh->rtnh_ifindex = src->rtnh_ifindex;
65 nh->rtnh_realms = src->rtnh_realms;
66 nh->ce_mask = src->ce_mask;
68 if (src->rtnh_gateway) {
70 if (!nh->rtnh_gateway)
74 if (src->rtnh_newdst) {
87 if (src->rtnh_encap) {
88 nh->rtnh_encap = rtnl_nh_encap_clone(src->rtnh_encap);
93 return _nl_steal_pointer(&nh);
96void rtnl_route_nh_free(
struct rtnl_nexthop *nh)
101 rtnl_nh_encap_free(nh->rtnh_encap);
107int rtnl_route_nh_compare(
struct rtnl_nexthop *a,
struct rtnl_nexthop *b,
108 uint32_t attrs,
int loose)
112#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
113 diff |= _DIFF(NH_ATTR_IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
114 diff |= _DIFF(NH_ATTR_WEIGHT, a->rtnh_weight != b->rtnh_weight);
115 diff |= _DIFF(NH_ATTR_REALMS, a->rtnh_realms != b->rtnh_realms);
116 diff |= _DIFF(NH_ATTR_GATEWAY,
118 diff |= _DIFF(NH_ATTR_NEWDST,
120 diff |= _DIFF(NH_ATTR_VIA,
nl_addr_cmp(a->rtnh_via, b->rtnh_via));
121 diff |= _DIFF(NH_ATTR_ENCAP,
122 nh_encap_compare(a->rtnh_encap, b->rtnh_encap));
125 diff |= _DIFF(NH_ATTR_FLAGS, (a->rtnh_flags ^ b->rtnh_flags) &
128 diff |= _DIFF(NH_ATTR_FLAGS, a->rtnh_flags != b->rtnh_flags);
145 return !rtnl_route_nh_compare(a, b,
146 NH_ATTR_IFINDEX | NH_ATTR_REALMS |
147 NH_ATTR_GATEWAY | NH_ATTR_NEWDST |
148 NH_ATTR_VIA | NH_ATTR_ENCAP,
152static void nh_dump_line(
struct rtnl_nexthop *nh,
struct nl_dump_params *dp)
154 struct nl_cache *link_cache;
159 if (nh->ce_mask & NH_ATTR_ENCAP)
160 nh_encap_dump(nh->rtnh_encap, dp);
162 if (nh->ce_mask & NH_ATTR_NEWDST)
168 if (nh->ce_mask & NH_ATTR_VIA)
171 if (nh->ce_mask & NH_ATTR_GATEWAY)
175 if (nh->ce_mask & NH_ATTR_IFINDEX) {
181 nl_dump(dp,
" dev %d", nh->rtnh_ifindex);
187 nl_cache_put(link_cache);
190static void nh_dump_details(
struct rtnl_nexthop *nh,
struct nl_dump_params *dp)
192 struct nl_cache *link_cache;
199 if (nh->ce_mask & NH_ATTR_ENCAP)
200 nh_encap_dump(nh->rtnh_encap, dp);
202 if (nh->ce_mask & NH_ATTR_NEWDST)
206 if (nh->ce_mask & NH_ATTR_VIA)
210 if (nh->ce_mask & NH_ATTR_GATEWAY)
214 if (nh->ce_mask & NH_ATTR_IFINDEX) {
220 nl_dump(dp,
" dev %d", nh->rtnh_ifindex);
223 if (nh->ce_mask & NH_ATTR_WEIGHT)
224 nl_dump(dp,
" weight %u", nh->rtnh_weight);
226 if (nh->ce_mask & NH_ATTR_REALMS)
227 nl_dump(dp,
" realm %04x:%04x",
231 if (nh->ce_mask & NH_ATTR_FLAGS)
233 rtnl_route_nh_flags2str(nh->rtnh_flags, buf,
237 nl_cache_put(link_cache);
240void rtnl_route_nh_dump(
struct rtnl_nexthop *nh,
struct nl_dump_params *dp)
244 nh_dump_line(nh, dp);
249 if (dp->
dp_ivar == NH_DUMP_FROM_DETAILS)
250 nh_dump_details(nh, dp);
263void rtnl_route_nh_set_weight(
struct rtnl_nexthop *nh, uint8_t weight)
265 nh->rtnh_weight = weight;
266 nh->ce_mask |= NH_ATTR_WEIGHT;
269uint8_t rtnl_route_nh_get_weight(
struct rtnl_nexthop *nh)
271 return nh->rtnh_weight;
274void rtnl_route_nh_set_ifindex(
struct rtnl_nexthop *nh,
int ifindex)
276 nh->rtnh_ifindex = ifindex;
277 nh->ce_mask |= NH_ATTR_IFINDEX;
280int rtnl_route_nh_get_ifindex(
struct rtnl_nexthop *nh)
282 return nh->rtnh_ifindex;
286void rtnl_route_nh_set_gateway(
struct rtnl_nexthop *nh,
struct nl_addr *addr)
288 struct nl_addr *old = nh->rtnh_gateway;
292 nh->ce_mask |= NH_ATTR_GATEWAY;
294 nh->ce_mask &= ~NH_ATTR_GATEWAY;
295 nh->rtnh_gateway = NULL;
302struct nl_addr *rtnl_route_nh_get_gateway(
struct rtnl_nexthop *nh)
304 return nh->rtnh_gateway;
307void rtnl_route_nh_set_flags(
struct rtnl_nexthop *nh,
unsigned int flags)
309 nh->rtnh_flag_mask |= flags;
310 nh->rtnh_flags |= flags;
311 nh->ce_mask |= NH_ATTR_FLAGS;
314void rtnl_route_nh_unset_flags(
struct rtnl_nexthop *nh,
unsigned int flags)
316 nh->rtnh_flag_mask |= flags;
317 nh->rtnh_flags &= ~flags;
318 nh->ce_mask |= NH_ATTR_FLAGS;
321unsigned int rtnl_route_nh_get_flags(
struct rtnl_nexthop *nh)
323 return nh->rtnh_flags;
326void rtnl_route_nh_set_realms(
struct rtnl_nexthop *nh, uint32_t realms)
328 nh->rtnh_realms = realms;
329 nh->ce_mask |= NH_ATTR_REALMS;
332uint32_t rtnl_route_nh_get_realms(
struct rtnl_nexthop *nh)
334 return nh->rtnh_realms;
337int rtnl_route_nh_set_newdst(
struct rtnl_nexthop *nh,
struct nl_addr *addr)
339 struct nl_addr *old = nh->rtnh_newdst;
343 nh->ce_mask |= NH_ATTR_NEWDST;
345 nh->ce_mask &= ~NH_ATTR_NEWDST;
346 nh->rtnh_newdst = NULL;
355struct nl_addr *rtnl_route_nh_get_newdst(
struct rtnl_nexthop *nh)
357 return nh->rtnh_newdst;
360int rtnl_route_nh_set_via(
struct rtnl_nexthop *nh,
struct nl_addr *addr)
362 struct nl_addr *old = nh->rtnh_via;
366 nh->ce_mask |= NH_ATTR_VIA;
368 nh->ce_mask &= ~NH_ATTR_VIA;
378struct nl_addr *rtnl_route_nh_get_via(
struct rtnl_nexthop *nh)
400 rtnl_nh_encap_free(nh_encap);
404 if (nh_encap && !nh_encap->ops) {
405 rtnl_nh_encap_free(nh_encap);
409 rtnl_nh_encap_free(nh->rtnh_encap);
412 nh->rtnh_encap = nh_encap;
413 nh->ce_mask |= NH_ATTR_ENCAP;
415 nh->rtnh_encap = NULL;
416 nh->ce_mask &= ~NH_ATTR_ENCAP;
429static const struct trans_tbl nh_flags[] = {
430 __ADD(RTNH_F_DEAD, dead),
431 __ADD(RTNH_F_PERVASIVE, pervasive),
432 __ADD(RTNH_F_ONLINK, onlink),
435char *rtnl_route_nh_flags2str(
int flags,
char *buf,
size_t len)
437 return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
440int rtnl_route_nh_str2flags(
const char *name)
442 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.
int rtnl_route_nh_set_encap(struct rtnl_nexthop *nh, struct rtnl_nh_encap *nh_encap)
Set nexthop encapsulation.
#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.