2 * lib/route/nexthop.c Routing Nexthop
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
14 * @defgroup nexthop Nexthop
18 #include <netlink-local.h>
19 #include <netlink/netlink.h>
20 #include <netlink/utils.h>
21 #include <netlink/route/rtnl.h>
22 #include <netlink/route/route.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
33 * @name Allocation/Freeing
37 struct rtnl_nexthop *rtnl_route_nh_alloc(void)
39 struct rtnl_nexthop *nh;
41 nh = calloc(1, sizeof(*nh));
45 nl_init_list_head(&nh->rtnh_list);
50 struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src)
52 struct rtnl_nexthop *nh;
54 nh = rtnl_route_nh_alloc();
58 nh->rtnh_flags = src->rtnh_flags;
59 nh->rtnh_flag_mask = src->rtnh_flag_mask;
60 nh->rtnh_weight = src->rtnh_weight;
61 nh->rtnh_ifindex = src->rtnh_ifindex;
62 nh->ce_mask = src->ce_mask;
64 if (src->rtnh_gateway) {
65 nh->rtnh_gateway = nl_addr_clone(src->rtnh_gateway);
66 if (!nh->rtnh_gateway) {
75 void rtnl_route_nh_free(struct rtnl_nexthop *nh)
77 nl_addr_put(nh->rtnh_gateway);
83 int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b,
84 uint32_t attrs, int loose)
88 #define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR)
90 diff |= NH_DIFF(IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
91 diff |= NH_DIFF(WEIGHT, a->rtnh_weight != b->rtnh_weight);
92 diff |= NH_DIFF(REALMS, a->rtnh_realms != b->rtnh_realms);
93 diff |= NH_DIFF(GATEWAY, nl_addr_cmp(a->rtnh_gateway,
97 diff |= NH_DIFF(FLAGS,
98 (a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask);
100 diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags);
107 static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
109 struct nl_cache *link_cache;
112 link_cache = nl_cache_mngt_require("route/link");
116 if (nh->ce_mask & NH_ATTR_GATEWAY)
117 nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway,
120 if(nh->ce_mask & NH_ATTR_IFINDEX) {
122 nl_dump(dp, " dev %s",
123 rtnl_link_i2name(link_cache,
127 nl_dump(dp, " dev %d", nh->rtnh_ifindex);
133 static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
135 struct nl_cache *link_cache;
138 link_cache = nl_cache_mngt_require("route/link");
140 nl_dump(dp, "nexthop");
142 if (nh->ce_mask & NH_ATTR_GATEWAY)
143 nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway,
146 if(nh->ce_mask & NH_ATTR_IFINDEX) {
148 nl_dump(dp, " dev %s",
149 rtnl_link_i2name(link_cache,
153 nl_dump(dp, " dev %d", nh->rtnh_ifindex);
156 if (nh->ce_mask & NH_ATTR_WEIGHT)
157 nl_dump(dp, " weight %u", nh->rtnh_weight);
159 if (nh->ce_mask & NH_ATTR_REALMS)
160 nl_dump(dp, " realm %04x:%04x",
161 RTNL_REALM_FROM(nh->rtnh_realms),
162 RTNL_REALM_TO(nh->rtnh_realms));
164 if (nh->ce_mask & NH_ATTR_FLAGS)
165 nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags,
169 static void nh_dump_env(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
171 struct nl_cache *link_cache;
174 link_cache = nl_cache_mngt_require("route/link");
176 if (nh->ce_mask & NH_ATTR_GATEWAY)
177 nl_dump_line(dp, "ROUTE_NH%d_VIA=%s\n", dp->dp_ivar,
178 nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf)));
180 if(nh->ce_mask & NH_ATTR_IFINDEX) {
182 nl_dump_line(dp, "ROUTE_NH%d_DEV=%s\n", dp->dp_ivar,
183 rtnl_link_i2name(link_cache,
187 nl_dump_line(dp, "ROUTE_NH%d_DEV=%d\n", dp->dp_ivar,
191 if (nh->ce_mask & NH_ATTR_WEIGHT)
192 nl_dump_line(dp, "ROUTE_NH%d_WEIGHT=%u\n", dp->dp_ivar,
195 if (nh->ce_mask & NH_ATTR_REALMS)
196 nl_dump_line(dp, "ROUTE_NH%d_REALM=%04x:%04x\n", dp->dp_ivar,
197 RTNL_REALM_FROM(nh->rtnh_realms),
198 RTNL_REALM_TO(nh->rtnh_realms));
200 if (nh->ce_mask & NH_ATTR_FLAGS)
201 nl_dump_line(dp, "ROUTE_NH%d_FLAGS=<%s>\n", dp->dp_ivar,
202 rtnl_route_nh_flags2str(nh->rtnh_flags,
205 void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
207 switch (dp->dp_type) {
209 nh_dump_line(nh, dp);
212 case NL_DUMP_DETAILS:
214 if (dp->dp_ivar == NH_DUMP_FROM_DETAILS)
215 nh_dump_details(nh, dp);
232 void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, uint8_t weight)
234 nh->rtnh_weight = weight;
235 nh->ce_mask |= NH_ATTR_WEIGHT;
238 uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *nh)
240 return nh->rtnh_weight;
243 void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *nh, int ifindex)
245 nh->rtnh_ifindex = ifindex;
246 nh->ce_mask |= NH_ATTR_IFINDEX;
249 int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh)
251 return nh->rtnh_ifindex;
254 void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr)
256 struct nl_addr *old = nh->rtnh_gateway;
259 nh->rtnh_gateway = nl_addr_get(addr);
260 nh->ce_mask |= NH_ATTR_GATEWAY;
262 nh->ce_mask &= ~NH_ATTR_GATEWAY;
263 nh->rtnh_gateway = NULL;
270 struct nl_addr *rtnl_route_nh_get_gateway(struct rtnl_nexthop *nh)
272 return nh->rtnh_gateway;
275 void rtnl_route_nh_set_flags(struct rtnl_nexthop *nh, unsigned int flags)
277 nh->rtnh_flag_mask |= flags;
278 nh->rtnh_flags |= flags;
279 nh->ce_mask |= NH_ATTR_FLAGS;
282 void rtnl_route_nh_unset_flags(struct rtnl_nexthop *nh, unsigned int flags)
284 nh->rtnh_flag_mask |= flags;
285 nh->rtnh_flags &= ~flags;
286 nh->ce_mask |= NH_ATTR_FLAGS;
289 unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *nh)
291 return nh->rtnh_flags;
294 void rtnl_route_nh_set_realms(struct rtnl_nexthop *nh, uint32_t realms)
296 nh->rtnh_realms = realms;
297 nh->ce_mask |= NH_ATTR_REALMS;
300 uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh)
302 return nh->rtnh_realms;
308 * @name Nexthop Flags Translations
312 static struct trans_tbl nh_flags[] = {
313 __ADD(RTNH_F_DEAD, dead)
314 __ADD(RTNH_F_PERVASIVE, pervasive)
315 __ADD(RTNH_F_ONLINK, onlink)
318 char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len)
320 return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
323 int rtnl_route_nh_str2flags(const char *name)
325 return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));