summaryrefslogtreecommitdiff
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c359
1 files changed, 264 insertions, 95 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 4913aa878f..d88dc05b28 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * 02111-1307, USA.
*/
#include <zebra.h>
@@ -40,6 +40,7 @@
#include "privs.h"
#include "nexthop.h"
#include "vrf.h"
+#include "vty.h"
#include "mpls.h"
#include "zebra/zserv.h"
@@ -54,6 +55,8 @@
#include "zebra/zebra_mpls.h"
#include "zebra/kernel_netlink.h"
#include "zebra/rt_netlink.h"
+#include "zebra/zebra_mroute.h"
+
/* TODO - Temporary definitions, need to refine. */
#ifndef AF_MPLS
@@ -76,6 +79,10 @@
#define RTA_ENCAP 22
#endif
+#ifndef RTA_EXPIRES
+#define RTA_EXPIRES 23
+#endif
+
#ifndef LWTUNNEL_ENCAP_MPLS
#define LWTUNNEL_ENCAP_MPLS 1
#endif
@@ -83,6 +90,10 @@
#ifndef MPLS_IPTUNNEL_DST
#define MPLS_IPTUNNEL_DST 1
#endif
+
+#ifndef NDA_MASTER
+#define NDA_MASTER 9
+#endif
/* End of temporary definitions */
struct gw_family_t
@@ -123,18 +134,20 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
struct rtattr *tb[RTA_MAX + 1];
u_char flags = 0;
struct prefix p;
+ struct prefix_ipv6 src_p;
vrf_id_t vrf_id = VRF_DEFAULT;
char anyaddr[16] = { 0 };
- int index;
+ int index = 0;
int table;
- int metric;
+ int metric = 0;
u_int32_t mtu = 0;
- void *dest;
- void *gate;
- void *src;
+ void *dest = NULL;
+ void *gate = NULL;
+ void *prefsrc = NULL; /* IPv4 preferred source host address */
+ void *src = NULL; /* IPv6 srcdest source prefix */
rtm = NLMSG_DATA (h);
@@ -157,9 +170,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (rtm->rtm_protocol == RTPROT_KERNEL)
return 0;
- if (rtm->rtm_src_len != 0)
- return 0;
-
/* We don't care about change notifications for the MPLS table. */
/* TODO: Revisit this. */
if (rtm->rtm_family == AF_MPLS)
@@ -184,12 +194,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (rtm->rtm_protocol == RTPROT_ZEBRA)
flags |= ZEBRA_FLAG_SELFROUTE;
- index = 0;
- metric = 0;
- dest = NULL;
- gate = NULL;
- src = NULL;
-
if (tb[RTA_OIF])
index = *(int *) RTA_DATA (tb[RTA_OIF]);
@@ -198,8 +202,13 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
else
dest = anyaddr;
+ if (tb[RTA_SRC])
+ src = RTA_DATA (tb[RTA_SRC]);
+ else
+ src = anyaddr;
+
if (tb[RTA_PREFSRC])
- src = RTA_DATA (tb[RTA_PREFSRC]);
+ prefsrc = RTA_DATA (tb[RTA_PREFSRC]);
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
@@ -225,9 +234,12 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
memcpy (&p.u.prefix4, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
+ if (rtm->rtm_src_len != 0)
+ return 0;
+
if (!tb[RTA_MULTIPATH])
rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
- 0, flags, &p, gate, src, index,
+ 0, flags, &p, NULL, gate, prefsrc, index,
table, metric, mtu, 0);
else
{
@@ -269,9 +281,9 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (gate)
{
if (index)
- rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
+ rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
else
- rib_nexthop_ipv4_add (rib, gate, src);
+ rib_nexthop_ipv4_add (rib, gate, prefsrc);
}
else
rib_nexthop_ifindex_add (rib, index);
@@ -285,7 +297,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (rib->nexthop_num == 0)
XFREE (MTYPE_RIB, rib);
else
- rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib);
+ rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib);
}
}
if (rtm->rtm_family == AF_INET6)
@@ -294,8 +306,12 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
memcpy (&p.u.prefix6, dest, 16);
p.prefixlen = rtm->rtm_dst_len;
+ src_p.family = AF_INET6;
+ memcpy (&src_p.prefix, src, 16);
+ src_p.prefixlen = rtm->rtm_src_len;
+
rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
- 0, flags, &p, gate, src, index,
+ 0, flags, &p, &src_p, gate, prefsrc, index,
table, metric, mtu, 0);
}
@@ -303,8 +319,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
}
/* Routing information change from the kernel. */
-int
-netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
+static int
+netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
ns_id_t ns_id)
{
int len;
@@ -313,49 +329,21 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
u_char zebra_flags = 0;
struct prefix p;
vrf_id_t vrf_id = VRF_DEFAULT;
-
char anyaddr[16] = { 0 };
- int index;
+ int index = 0;
int table;
- int metric;
+ int metric = 0;
u_int32_t mtu = 0;
- void *dest;
- void *gate;
- void *src;
+ void *dest = NULL;
+ void *gate = NULL;
+ void *prefsrc = NULL; /* IPv4 preferred source host address */
+ void *src = NULL; /* IPv6 srcdest source prefix */
rtm = NLMSG_DATA (h);
- if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
- {
- /* If this is not route add/delete message print warning. */
- zlog_warn ("Kernel message: %d", h->nlmsg_type);
- return 0;
- }
-
- /* Connected route. */
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s %s %s proto %s",
- h->nlmsg_type ==
- RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
- rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
- rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
- nl_rtproto_to_str (rtm->rtm_protocol));
-
- if (rtm->rtm_type != RTN_UNICAST)
- {
- return 0;
- }
-
- /* We don't care about change notifications for the MPLS table. */
- /* TODO: Revisit this. */
- if (rtm->rtm_family == AF_MPLS)
- return 0;
-
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
- if (len < 0)
- return -1;
memset (tb, 0, sizeof tb);
netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
@@ -372,12 +360,6 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (rtm->rtm_protocol == RTPROT_ZEBRA)
SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
- if (rtm->rtm_src_len != 0)
- {
- zlog_warn ("netlink_route_change(): no src len");
- return 0;
- }
-
/* Table corresponding to route. */
if (tb[RTA_TABLE])
table = *(int *) RTA_DATA (tb[RTA_TABLE]);
@@ -393,12 +375,6 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
return 0;
}
- index = 0;
- metric = 0;
- dest = NULL;
- gate = NULL;
- src = NULL;
-
if (tb[RTA_OIF])
index = *(int *) RTA_DATA (tb[RTA_OIF]);
@@ -407,11 +383,16 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
else
dest = anyaddr;
+ if (tb[RTA_SRC])
+ src = RTA_DATA (tb[RTA_SRC]);
+ else
+ src = anyaddr;
+
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
if (tb[RTA_PREFSRC])
- src = RTA_DATA (tb[RTA_PREFSRC]);
+ prefsrc = RTA_DATA (tb[RTA_PREFSRC]);
if (h->nlmsg_type == RTM_NEWROUTE)
{
@@ -437,11 +418,18 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
memcpy (&p.u.prefix4, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
+ if (rtm->rtm_src_len != 0)
+ {
+ zlog_warn ("unsupported IPv4 sourcedest route (dest %s/%d)",
+ inet_ntoa (p.u.prefix4), p.prefixlen);
+ return 0;
+ }
+
if (IS_ZEBRA_DEBUG_KERNEL)
{
char buf[PREFIX_STRLEN];
zlog_debug ("%s %s vrf %u",
- h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
+ nl_msg_type_to_str (h->nlmsg_type),
prefix2str (&p, buf, sizeof(buf)), vrf_id);
}
@@ -449,8 +437,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
{
if (!tb[RTA_MULTIPATH])
rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
- 0, 0, &p, gate, src, index,
- table, metric, mtu, 0);
+ 0, 0, &p, NULL, gate, prefsrc, index,
+ table, metric, mtu, 0);
else
{
/* This is a multipath route */
@@ -491,9 +479,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (gate)
{
if (index)
- rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
+ rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
else
- rib_nexthop_ipv4_add (rib, gate, src);
+ rib_nexthop_ipv4_add (rib, gate, prefsrc);
}
else
rib_nexthop_ifindex_add (rib, index);
@@ -508,37 +496,183 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (rib->nexthop_num == 0)
XFREE (MTYPE_RIB, rib);
else
- rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib);
+ rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib);
}
}
else
rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
- &p, gate, index, table);
+ &p, NULL, gate, index, table);
}
if (rtm->rtm_family == AF_INET6)
{
struct prefix p;
+ struct prefix_ipv6 src_p;
p.family = AF_INET6;
memcpy (&p.u.prefix6, dest, 16);
p.prefixlen = rtm->rtm_dst_len;
+ src_p.family = AF_INET6;
+ memcpy (&src_p.prefix, src, 16);
+ src_p.prefixlen = rtm->rtm_src_len;
+
if (IS_ZEBRA_DEBUG_KERNEL)
{
char buf[PREFIX_STRLEN];
- zlog_debug ("%s %s vrf %u",
- h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
- prefix2str (&p, buf, sizeof(buf)), vrf_id);
+ char buf2[PREFIX_STRLEN];
+ zlog_debug ("%s %s%s%s vrf %u",
+ nl_msg_type_to_str (h->nlmsg_type),
+ prefix2str (&p, buf, sizeof(buf)),
+ src_p.prefixlen ? " from " : "",
+ src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
+ vrf_id);
}
if (h->nlmsg_type == RTM_NEWROUTE)
rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
- 0, 0, &p, gate, src, index,
+ 0, 0, &p, &src_p, gate, prefsrc, index,
table, metric, mtu, 0);
else
rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
- 0, zebra_flags, &p, gate, index, table);
+ 0, zebra_flags, &p, &src_p, gate, index, table);
+ }
+
+ return 0;
+}
+
+static struct mcast_route_data *mroute = NULL;
+
+static int
+netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
+ ns_id_t ns_id)
+{
+ int len;
+ struct rtmsg *rtm;
+ struct rtattr *tb[RTA_MAX + 1];
+ struct mcast_route_data *m;
+ struct mcast_route_data mr;
+ int iif = 0;
+ int count;
+ int oif[256];
+ int oif_count = 0;
+ char sbuf[40];
+ char gbuf[40];
+ char oif_list[256] = "\0";
+ vrf_id_t vrf = ns_id;
+
+ if (mroute)
+ m = mroute;
+ else
+ {
+ memset (&mr, 0, sizeof (mr));
+ m = &mr;
+ }
+
+ rtm = NLMSG_DATA (h);
+
+ len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
+
+ memset (tb, 0, sizeof tb);
+ netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
+
+ if (tb[RTA_IIF])
+ iif = *(int *)RTA_DATA (tb[RTA_IIF]);
+
+ if (tb[RTA_SRC])
+ m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]);
+
+ if (tb[RTA_DST])
+ m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]);
+
+ if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES])
+ m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]);
+
+ if (tb[RTA_MULTIPATH])
+ {
+ struct rtnexthop *rtnh =
+ (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]);
+
+ len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
+ for (;;)
+ {
+ if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
+ break;
+
+ oif[oif_count] = rtnh->rtnh_ifindex;
+ oif_count++;
+
+ len -= NLMSG_ALIGN (rtnh->rtnh_len);
+ rtnh = RTNH_NEXT (rtnh);
+ }
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ {
+ struct interface *ifp;
+ strcpy (sbuf, inet_ntoa (m->sg.src));
+ strcpy (gbuf, inet_ntoa (m->sg.grp));
+ for (count = 0; count < oif_count; count++)
+ {
+ ifp = if_lookup_by_index_vrf (oif[count], vrf);
+ char temp[256];
+
+ sprintf (temp, "%s ", ifp->name);
+ strcat (oif_list, temp);
+ }
+ ifp = if_lookup_by_index_vrf (iif, vrf);
+ zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
+ nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused);
+ }
+ return 0;
+}
+
+int
+netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
+ ns_id_t ns_id)
+{
+ int len;
+ vrf_id_t vrf_id = ns_id;
+ struct rtmsg *rtm;
+
+ rtm = NLMSG_DATA (h);
+
+ if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
+ {
+ /* If this is not route add/delete message print warning. */
+ zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
+ return 0;
+ }
+
+ /* Connected route. */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug ("%s %s %s proto %s vrf %u",
+ nl_msg_type_to_str (h->nlmsg_type),
+ nl_family_to_str (rtm->rtm_family),
+ nl_rttype_to_str (rtm->rtm_type),
+ nl_rtproto_to_str (rtm->rtm_protocol),
+ vrf_id);
+
+ /* We don't care about change notifications for the MPLS table. */
+ /* TODO: Revisit this. */
+ if (rtm->rtm_family == AF_MPLS)
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
+ if (len < 0)
+ return -1;
+
+ switch (rtm->rtm_type)
+ {
+ case RTN_UNICAST:
+ netlink_route_change_read_unicast (snl, h, ns_id);
+ break;
+ case RTN_MULTICAST:
+ netlink_route_change_read_multicast (snl, h, ns_id);
+ break;
+ default:
+ return 0;
+ break;
}
return 0;
@@ -559,7 +693,6 @@ netlink_route_read (struct zebra_ns *zns)
if (ret < 0)
return ret;
-#ifdef HAVE_IPV6
/* Get IPv6 routing table. */
ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd);
if (ret < 0)
@@ -567,7 +700,6 @@ netlink_route_read (struct zebra_ns *zns)
ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0);
if (ret < 0)
return ret;
-#endif /* HAVE_IPV6 */
return 0;
}
@@ -693,7 +825,7 @@ _netlink_route_build_singlepath(
int i, num_labels = 0;
u_int32_t bos;
char label_buf1[20];
-
+
for (i = 0; i < nh_label->num_labels; i++)
{
if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
@@ -1074,7 +1206,7 @@ _netlink_route_debug(
prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf),
(nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK");
}
-}
+ }
static void
_netlink_mpls_debug(
@@ -1112,14 +1244,14 @@ netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen
addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
- return netlink_talk (&req.n, &zns->netlink_cmd, zns);
+ return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
}
/* Routing table change via netlink interface. */
/* Update flag indicates whether this is a "replace" or not. */
static int
-netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
- int update)
+netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
+ struct rib *rib, int update)
{
int bytelen;
struct sockaddr_nl snl;
@@ -1153,6 +1285,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
req.n.nlmsg_type = cmd;
req.r.rtm_family = family;
req.r.rtm_dst_len = p->prefixlen;
+ req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
req.r.rtm_protocol = RTPROT_ZEBRA;
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
@@ -1177,6 +1310,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
}
addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
+ if (src_p)
+ addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen);
/* Metric. */
/* Hardcode the metric for all routes coming from zebra. Metric isn't used
@@ -1407,18 +1542,52 @@ skip:
snl.nl_family = AF_NETLINK;
/* Talk to netlink socket. */
- return netlink_talk (&req.n, &zns->netlink_cmd, zns);
+ return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
+}
+
+int
+kernel_get_ipmr_sg_stats (void *in)
+{
+ int suc = 0;
+ struct mcast_route_data *mr = (struct mcast_route_data *)in;
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
+
+ mroute = mr;
+ struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
+
+ memset(&req.n, 0, sizeof(req.n));
+ memset(&req.ndm, 0, sizeof(req.ndm));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.ndm.ndm_family = AF_INET;
+ req.n.nlmsg_type = RTM_GETROUTE;
+
+ addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4);
+ addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4);
+ addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4);
+ addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4);
+
+ suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns);
+
+ mroute = NULL;
+ return suc;
}
int
-kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
+kernel_route_rib (struct prefix *p, struct prefix *src_p,
+ struct rib *old, struct rib *new)
{
if (!old && new)
- return netlink_route_multipath (RTM_NEWROUTE, p, new, 0);
+ return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0);
if (old && !new)
- return netlink_route_multipath (RTM_DELROUTE, p, old, 0);
+ return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0);
- return netlink_route_multipath (RTM_NEWROUTE, p, new, 1);
+ return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1);
}
int
@@ -1597,7 +1766,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
}
/* Talk to netlink socket. */
- return netlink_talk (&req.n, &zns->netlink_cmd, zns);
+ return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
}
/*