summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_fpm_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_fpm_netlink.c')
-rw-r--r--zebra/zebra_fpm_netlink.c619
1 files changed, 295 insertions, 324 deletions
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index d935826db..862049cb8 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -43,25 +43,23 @@
*
* Returns string representation of an address of the given AF.
*/
-static inline const char *
-addr_to_a (u_char af, void *addr)
+static inline const char *addr_to_a(u_char af, void *addr)
{
- if (!addr)
- return "<No address>";
-
- switch (af)
- {
-
- case AF_INET:
- return inet_ntoa (*((struct in_addr *) addr));
- break;
- case AF_INET6:
- return inet6_ntoa (*((struct in6_addr *) addr));
- break;
- default:
- return "<Addr in unknown AF>";
- break;
- }
+ if (!addr)
+ return "<No address>";
+
+ switch (af) {
+
+ case AF_INET:
+ return inet_ntoa(*((struct in_addr *)addr));
+ break;
+ case AF_INET6:
+ return inet6_ntoa(*((struct in6_addr *)addr));
+ break;
+ default:
+ return "<Addr in unknown AF>";
+ break;
+ }
}
/*
@@ -70,13 +68,12 @@ addr_to_a (u_char af, void *addr)
* Convience wrapper that returns a human-readable string for the
* address in a prefix.
*/
-static const char *
-prefix_addr_to_a (struct prefix *prefix)
+static const char *prefix_addr_to_a(struct prefix *prefix)
{
- if (!prefix)
- return "<No address>";
+ if (!prefix)
+ return "<No address>";
- return addr_to_a (prefix->family, &prefix->u.prefix);
+ return addr_to_a(prefix->family, &prefix->u.prefix);
}
/*
@@ -84,22 +81,20 @@ prefix_addr_to_a (struct prefix *prefix)
*
* The size of an address in a given address family.
*/
-static size_t
-af_addr_size (u_char af)
+static size_t af_addr_size(u_char af)
{
- switch (af)
- {
-
- case AF_INET:
- return 4;
- break;
- case AF_INET6:
- return 16;
- break;
- default:
- assert(0);
- return 16;
- }
+ switch (af) {
+
+ case AF_INET:
+ return 4;
+ break;
+ case AF_INET6:
+ return 16;
+ break;
+ default:
+ assert(0);
+ return 16;
+ }
}
/*
@@ -109,17 +104,16 @@ af_addr_size (u_char af)
* structures are transient and may contain pointers into rib
* data structures for convenience.
*/
-typedef struct netlink_nh_info_t_
-{
- uint32_t if_index;
- union g_addr *gateway;
-
- /*
- * Information from the struct nexthop from which this nh was
- * derived. For debug purposes only.
- */
- int recursive;
- enum nexthop_types_t type;
+typedef struct netlink_nh_info_t_ {
+ uint32_t if_index;
+ union g_addr *gateway;
+
+ /*
+ * Information from the struct nexthop from which this nh was
+ * derived. For debug purposes only.
+ */
+ int recursive;
+ enum nexthop_types_t type;
} netlink_nh_info_t;
/*
@@ -127,22 +121,21 @@ typedef struct netlink_nh_info_t_
*
* A structure for holding information for a netlink route message.
*/
-typedef struct netlink_route_info_t_
-{
- uint16_t nlmsg_type;
- u_char rtm_type;
- uint32_t rtm_table;
- u_char rtm_protocol;
- u_char af;
- struct prefix *prefix;
- uint32_t *metric;
- unsigned int num_nhs;
-
- /*
- * Nexthop structures
- */
- netlink_nh_info_t nhs[MULTIPATH_NUM];
- union g_addr *pref_src;
+typedef struct netlink_route_info_t_ {
+ uint16_t nlmsg_type;
+ u_char rtm_type;
+ uint32_t rtm_table;
+ u_char rtm_protocol;
+ u_char af;
+ struct prefix *prefix;
+ uint32_t *metric;
+ unsigned int num_nhs;
+
+ /*
+ * Nexthop structures
+ */
+ netlink_nh_info_t nhs[MULTIPATH_NUM];
+ union g_addr *pref_src;
} netlink_route_info_t;
/*
@@ -153,72 +146,67 @@ typedef struct netlink_route_info_t_
*
* Returns TRUE if a nexthop was added, FALSE otherwise.
*/
-static int
-netlink_route_info_add_nh (netlink_route_info_t *ri, struct nexthop *nexthop)
+static int netlink_route_info_add_nh(netlink_route_info_t *ri,
+ struct nexthop *nexthop)
{
- netlink_nh_info_t nhi;
- union g_addr *src;
-
- memset (&nhi, 0, sizeof (nhi));
- src = NULL;
-
- if (ri->num_nhs >= (int) ZEBRA_NUM_OF (ri->nhs))
- return 0;
-
- nhi.recursive = nexthop->rparent ? 1 : 0;
- nhi.type = nexthop->type;
- nhi.if_index = nexthop->ifindex;
-
- if (nexthop->type == NEXTHOP_TYPE_IPV4
- || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
- {
- nhi.gateway = &nexthop->gate;
- if (nexthop->src.ipv4.s_addr)
- src = &nexthop->src;
- }
-
- if (nexthop->type == NEXTHOP_TYPE_IPV6
- || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
- {
- nhi.gateway = &nexthop->gate;
- }
-
- if (nexthop->type == NEXTHOP_TYPE_IFINDEX)
- {
- if (nexthop->src.ipv4.s_addr)
- src = &nexthop->src;
- }
-
- if (!nhi.gateway && nhi.if_index == 0)
- return 0;
-
- /*
- * We have a valid nhi. Copy the structure over to the route_info.
- */
- ri->nhs[ri->num_nhs] = nhi;
- ri->num_nhs++;
-
- if (src && !ri->pref_src)
- ri->pref_src = src;
-
- return 1;
+ netlink_nh_info_t nhi;
+ union g_addr *src;
+
+ memset(&nhi, 0, sizeof(nhi));
+ src = NULL;
+
+ if (ri->num_nhs >= (int)ZEBRA_NUM_OF(ri->nhs))
+ return 0;
+
+ nhi.recursive = nexthop->rparent ? 1 : 0;
+ nhi.type = nexthop->type;
+ nhi.if_index = nexthop->ifindex;
+
+ if (nexthop->type == NEXTHOP_TYPE_IPV4
+ || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+ nhi.gateway = &nexthop->gate;
+ if (nexthop->src.ipv4.s_addr)
+ src = &nexthop->src;
+ }
+
+ if (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
+ nhi.gateway = &nexthop->gate;
+ }
+
+ if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
+ if (nexthop->src.ipv4.s_addr)
+ src = &nexthop->src;
+ }
+
+ if (!nhi.gateway && nhi.if_index == 0)
+ return 0;
+
+ /*
+ * We have a valid nhi. Copy the structure over to the route_info.
+ */
+ ri->nhs[ri->num_nhs] = nhi;
+ ri->num_nhs++;
+
+ if (src && !ri->pref_src)
+ ri->pref_src = src;
+
+ return 1;
}
/*
* netlink_proto_from_route_type
*/
-static u_char
-netlink_proto_from_route_type (int type)
+static u_char netlink_proto_from_route_type(int type)
{
- switch (type)
- {
- case ZEBRA_ROUTE_KERNEL:
- case ZEBRA_ROUTE_CONNECT:
- return RTPROT_KERNEL;
-
- default:
- return RTPROT_ZEBRA;
- }
+ switch (type) {
+ case ZEBRA_ROUTE_KERNEL:
+ case ZEBRA_ROUTE_CONNECT:
+ return RTPROT_KERNEL;
+
+ default:
+ return RTPROT_ZEBRA;
+ }
}
/*
@@ -228,87 +216,81 @@ netlink_proto_from_route_type (int type)
*
* Returns TRUE on success and FALSE on failure.
*/
-static int
-netlink_route_info_fill (netlink_route_info_t *ri, int cmd,
- rib_dest_t *dest, struct route_entry *re)
+static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
+ rib_dest_t *dest, struct route_entry *re)
{
- struct nexthop *nexthop;
- int discard;
-
- memset (ri, 0, sizeof (*ri));
-
- ri->prefix = rib_dest_prefix (dest);
- ri->af = rib_dest_af (dest);
-
- ri->nlmsg_type = cmd;
- ri->rtm_table = zvrf_id (rib_dest_vrf (dest));
- ri->rtm_protocol = RTPROT_UNSPEC;
-
- /*
- * An RTM_DELROUTE need not be accompanied by any nexthops,
- * particularly in our communication with the FPM.
- */
- if (cmd == RTM_DELROUTE && !re)
- return 1;
-
- if (!re)
- {
- zfpm_debug ("%s: Expected non-NULL re pointer", __PRETTY_FUNCTION__);
- return 0;
- }
-
- ri->rtm_protocol = netlink_proto_from_route_type (re->type);
-
- if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT))
- discard = 1;
- else
- discard = 0;
-
- if (cmd == RTM_NEWROUTE)
- {
- if (discard)
- {
- if (re->flags & ZEBRA_FLAG_BLACKHOLE)
- ri->rtm_type = RTN_BLACKHOLE;
- else if (re->flags & ZEBRA_FLAG_REJECT)
- ri->rtm_type = RTN_UNREACHABLE;
- else
- assert (0);
- }
- else
- ri->rtm_type = RTN_UNICAST;
- }
-
- ri->metric = &re->metric;
-
- if (discard)
- return 1;
-
- for (ALL_NEXTHOPS(re->nexthop, nexthop))
- {
- if (ri->num_nhs >= multipath_num)
- break;
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- continue;
-
- if ((cmd == RTM_NEWROUTE
- && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- || (cmd == RTM_DELROUTE
- && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
- {
- netlink_route_info_add_nh (ri, nexthop);
- }
- }
-
- /* If there is no useful nexthop then return. */
- if (ri->num_nhs == 0)
- {
- zfpm_debug ("netlink_encode_route(): No useful nexthop.");
- return 0;
- }
-
- return 1;
+ struct nexthop *nexthop;
+ int discard;
+
+ memset(ri, 0, sizeof(*ri));
+
+ ri->prefix = rib_dest_prefix(dest);
+ ri->af = rib_dest_af(dest);
+
+ ri->nlmsg_type = cmd;
+ ri->rtm_table = zvrf_id(rib_dest_vrf(dest));
+ ri->rtm_protocol = RTPROT_UNSPEC;
+
+ /*
+ * An RTM_DELROUTE need not be accompanied by any nexthops,
+ * particularly in our communication with the FPM.
+ */
+ if (cmd == RTM_DELROUTE && !re)
+ return 1;
+
+ if (!re) {
+ zfpm_debug("%s: Expected non-NULL re pointer",
+ __PRETTY_FUNCTION__);
+ return 0;
+ }
+
+ ri->rtm_protocol = netlink_proto_from_route_type(re->type);
+
+ if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
+ || (re->flags & ZEBRA_FLAG_REJECT))
+ discard = 1;
+ else
+ discard = 0;
+
+ if (cmd == RTM_NEWROUTE) {
+ if (discard) {
+ if (re->flags & ZEBRA_FLAG_BLACKHOLE)
+ ri->rtm_type = RTN_BLACKHOLE;
+ else if (re->flags & ZEBRA_FLAG_REJECT)
+ ri->rtm_type = RTN_UNREACHABLE;
+ else
+ assert(0);
+ } else
+ ri->rtm_type = RTN_UNICAST;
+ }
+
+ ri->metric = &re->metric;
+
+ if (discard)
+ return 1;
+
+ for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+ if (ri->num_nhs >= multipath_num)
+ break;
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ continue;
+
+ if ((cmd == RTM_NEWROUTE
+ && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ || (cmd == RTM_DELROUTE
+ && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) {
+ netlink_route_info_add_nh(ri, nexthop);
+ }
+ }
+
+ /* If there is no useful nexthop then return. */
+ if (ri->num_nhs == 0) {
+ zfpm_debug("netlink_encode_route(): No useful nexthop.");
+ return 0;
+ }
+
+ return 1;
}
/*
@@ -317,122 +299,114 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd,
* Returns the number of bytes written to the buffer. 0 or a negative
* value indicates an error.
*/
-static int
-netlink_route_info_encode (netlink_route_info_t *ri, char *in_buf,
- size_t in_buf_len)
+static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf,
+ size_t in_buf_len)
{
- size_t bytelen;
- unsigned int nexthop_num = 0;
- size_t buf_offset;
- netlink_nh_info_t *nhi;
+ size_t bytelen;
+ unsigned int nexthop_num = 0;
+ size_t buf_offset;
+ netlink_nh_info_t *nhi;
- struct
- {
- struct nlmsghdr n;
- struct rtmsg r;
- char buf[1];
- } *req;
+ struct {
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[1];
+ } * req;
- req = (void *) in_buf;
+ req = (void *)in_buf;
- buf_offset = ((char *) req->buf) - ((char *) req);
+ buf_offset = ((char *)req->buf) - ((char *)req);
- if (in_buf_len < buf_offset) {
- assert(0);
- return 0;
- }
-
- memset (req, 0, buf_offset);
-
- bytelen = af_addr_size (ri->af);
-
- req->n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
- req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- req->n.nlmsg_type = ri->nlmsg_type;
- req->r.rtm_family = ri->af;
- req->r.rtm_table = ri->rtm_table;
- req->r.rtm_dst_len = ri->prefix->prefixlen;
- req->r.rtm_protocol = ri->rtm_protocol;
- req->r.rtm_scope = RT_SCOPE_UNIVERSE;
-
- addattr_l (&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix, bytelen);
-
- req->r.rtm_type = ri->rtm_type;
-
- /* Metric. */
- if (ri->metric)
- addattr32 (&req->n, in_buf_len, RTA_PRIORITY, *ri->metric);
+ if (in_buf_len < buf_offset) {
+ assert(0);
+ return 0;
+ }
- if (ri->num_nhs == 0)
- goto done;
+ memset(req, 0, buf_offset);
- if (ri->num_nhs == 1)
- {
- nhi = &ri->nhs[0];
+ bytelen = af_addr_size(ri->af);
- if (nhi->gateway)
- {
- addattr_l (&req->n, in_buf_len, RTA_GATEWAY, nhi->gateway,
- bytelen);
- }
+ req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+ req->n.nlmsg_type = ri->nlmsg_type;
+ req->r.rtm_family = ri->af;
+ req->r.rtm_table = ri->rtm_table;
+ req->r.rtm_dst_len = ri->prefix->prefixlen;
+ req->r.rtm_protocol = ri->rtm_protocol;
+ req->r.rtm_scope = RT_SCOPE_UNIVERSE;
- if (nhi->if_index)
- {
- addattr32 (&req->n, in_buf_len, RTA_OIF, nhi->if_index);
- }
+ addattr_l(&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix, bytelen);
- goto done;
+ req->r.rtm_type = ri->rtm_type;
- }
+ /* Metric. */
+ if (ri->metric)
+ addattr32(&req->n, in_buf_len, RTA_PRIORITY, *ri->metric);
- /*
- * Multipath case.
- */
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *) buf;
- struct rtnexthop *rtnh;
+ if (ri->num_nhs == 0)
+ goto done;
- rta->rta_type = RTA_MULTIPATH;
- rta->rta_len = RTA_LENGTH (0);
- rtnh = RTA_DATA (rta);
+ if (ri->num_nhs == 1) {
+ nhi = &ri->nhs[0];
- for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++)
- {
- nhi = &ri->nhs[nexthop_num];
+ if (nhi->gateway) {
+ addattr_l(&req->n, in_buf_len, RTA_GATEWAY,
+ nhi->gateway, bytelen);
+ }
- rtnh->rtnh_len = sizeof (*rtnh);
- rtnh->rtnh_flags = 0;
- rtnh->rtnh_hops = 0;
- rtnh->rtnh_ifindex = 0;
- rta->rta_len += rtnh->rtnh_len;
+ if (nhi->if_index) {
+ addattr32(&req->n, in_buf_len, RTA_OIF, nhi->if_index);
+ }
- if (nhi->gateway)
- {
- rta_addattr_l (rta, sizeof (buf), RTA_GATEWAY, nhi->gateway, bytelen);
- rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
+ goto done;
}
- if (nhi->if_index)
- {
- rtnh->rtnh_ifindex = nhi->if_index;
+ /*
+ * Multipath case.
+ */
+ char buf[NL_PKT_BUF_SIZE];
+ struct rtattr *rta = (void *)buf;
+ struct rtnexthop *rtnh;
+
+ rta->rta_type = RTA_MULTIPATH;
+ rta->rta_len = RTA_LENGTH(0);
+ rtnh = RTA_DATA(rta);
+
+ for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++) {
+ nhi = &ri->nhs[nexthop_num];
+
+ rtnh->rtnh_len = sizeof(*rtnh);
+ rtnh->rtnh_flags = 0;
+ rtnh->rtnh_hops = 0;
+ rtnh->rtnh_ifindex = 0;
+ rta->rta_len += rtnh->rtnh_len;
+
+ if (nhi->gateway) {
+ rta_addattr_l(rta, sizeof(buf), RTA_GATEWAY,
+ nhi->gateway, bytelen);
+ rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
+ }
+
+ if (nhi->if_index) {
+ rtnh->rtnh_ifindex = nhi->if_index;
+ }
+
+ rtnh = RTNH_NEXT(rtnh);
}
- rtnh = RTNH_NEXT (rtnh);
- }
-
- assert (rta->rta_len > RTA_LENGTH (0));
- addattr_l (&req->n, in_buf_len, RTA_MULTIPATH, RTA_DATA (rta),
- RTA_PAYLOAD (rta));
+ assert(rta->rta_len > RTA_LENGTH(0));
+ addattr_l(&req->n, in_buf_len, RTA_MULTIPATH, RTA_DATA(rta),
+ RTA_PAYLOAD(rta));
done:
- if (ri->pref_src)
- {
- addattr_l (&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src, bytelen);
- }
+ if (ri->pref_src) {
+ addattr_l(&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src,
+ bytelen);
+ }
- assert (req->n.nlmsg_len < in_buf_len);
- return req->n.nlmsg_len;
+ assert(req->n.nlmsg_len < in_buf_len);
+ return req->n.nlmsg_len;
}
/*
@@ -440,26 +414,24 @@ done:
*
* Helper function to log the information in a route_info structure.
*/
-static void
-zfpm_log_route_info (netlink_route_info_t *ri, const char *label)
+static void zfpm_log_route_info(netlink_route_info_t *ri, const char *label)
{
- netlink_nh_info_t *nhi;
- unsigned int i;
-
- zfpm_debug ("%s : %s %s/%d, Proto: %s, Metric: %u", label,
- nl_msg_type_to_str (ri->nlmsg_type),
- prefix_addr_to_a (ri->prefix), ri->prefix->prefixlen,
- nl_rtproto_to_str (ri->rtm_protocol),
- ri->metric ? *ri->metric : 0);
-
- for (i = 0; i < ri->num_nhs; i++)
- {
- nhi = &ri->nhs[i];
- zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s",
- nhi->if_index, addr_to_a (ri->af, nhi->gateway),
- nhi->recursive ? "yes" : "no",
- nexthop_type_to_str (nhi->type));
- }
+ netlink_nh_info_t *nhi;
+ unsigned int i;
+
+ zfpm_debug("%s : %s %s/%d, Proto: %s, Metric: %u", label,
+ nl_msg_type_to_str(ri->nlmsg_type),
+ prefix_addr_to_a(ri->prefix), ri->prefix->prefixlen,
+ nl_rtproto_to_str(ri->rtm_protocol),
+ ri->metric ? *ri->metric : 0);
+
+ for (i = 0; i < ri->num_nhs; i++) {
+ nhi = &ri->nhs[i];
+ zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s",
+ nhi->if_index, addr_to_a(ri->af, nhi->gateway),
+ nhi->recursive ? "yes" : "no",
+ nexthop_type_to_str(nhi->type));
+ }
}
/*
@@ -471,18 +443,17 @@ zfpm_log_route_info (netlink_route_info_t *ri, const char *label)
* Returns the number of bytes written to the buffer. 0 or a negative
* value indicates an error.
*/
-int
-zfpm_netlink_encode_route (int cmd, rib_dest_t *dest, struct route_entry *re,
- char *in_buf, size_t in_buf_len)
+int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re,
+ char *in_buf, size_t in_buf_len)
{
- netlink_route_info_t ri_space, *ri;
+ netlink_route_info_t ri_space, *ri;
- ri = &ri_space;
+ ri = &ri_space;
- if (!netlink_route_info_fill (ri, cmd, dest, re))
- return 0;
+ if (!netlink_route_info_fill(ri, cmd, dest, re))
+ return 0;
- zfpm_log_route_info (ri, __FUNCTION__);
+ zfpm_log_route_info(ri, __FUNCTION__);
- return netlink_route_info_encode (ri, in_buf, in_buf_len);
+ return netlink_route_info_encode(ri, in_buf, in_buf_len);
}