*
* If ZAPI_MESSAGE_TAG is set, the tag value is written as a 2 byte value
*
+ * If ZAPI_MESSAGE_MTU is set, the mtu value is written as a 4 byte value
+ *
* XXX: No attention paid to alignment.
*/
int
stream_putl (s, api->metric);
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG))
stream_putw (s, api->tag);
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
+ stream_putl (s, api->mtu);
/* Put length at the first point of the stream. */
stream_putw_at (s, 0, stream_get_endp (s));
stream_putl (s, api->metric);
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG))
stream_putw (s, api->tag);
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
+ stream_putl (s, api->mtu);
/* Put length at the first point of the stream. */
stream_putw_at (s, 0, stream_get_endp (s));
stream_putl (s, api->metric);
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG))
stream_putw (s, api->tag);
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
+ stream_putl (s, api->mtu);
/* Put length at the first point of the stream. */
stream_putw_at (s, 0, stream_get_endp (s));
#define ZAPI_MESSAGE_DISTANCE 0x04
#define ZAPI_MESSAGE_METRIC 0x08
#define ZAPI_MESSAGE_TAG 0x10
+#define ZAPI_MESSAGE_MTU 0x20
/* Zserv protocol message header */
struct zserv_header
u_short tag;
+ u_int32_t mtu;
+
vrf_id_t vrf_id;
};
u_short tag;
+ u_int32_t mtu;
+
vrf_id_t vrf_id;
};
return;
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex,
- ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
+ ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex,
- ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
+ ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing",
#endif
rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
- RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
+ RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing",
|| rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
- &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST);
+ &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT,
+ 0, 0, 0, 0, SAFI_UNICAST);
else
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
&p, &gate.sin.sin_addr, 0, VRF_DEFAULT, 0, SAFI_UNICAST);
|| rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
- &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST);
+ &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT,
+ 0, 0, 0, 0, SAFI_UNICAST);
else
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
&p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, SAFI_UNICAST);
rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4,
gate, &nhop->src.ipv4,
nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default,
- rib->metric,
+ rib->metric, rib->mtu,
zebra_import_table_distance[AFI_IP][rib->table],
SAFI_UNICAST);
}
newrib->distance = zebra_import_table_distance[AFI_IP][rib->table];
newrib->flags = rib->flags;
newrib->metric = rib->metric;
+ newrib->mtu = rib->mtu;
newrib->table = zebrad.rtm_table_default;
newrib->nexthop_num = 0;
newrib->uptime = time(NULL);
/* Metric */
u_int32_t metric;
+ /* MTU */
+ u_int32_t mtu;
+ u_int32_t nexthop_mtu;
+
/* Distance. */
u_char distance;
extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src,
ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id,
- u_int32_t, u_char, safi_t);
+ u_int32_t, u_int32_t, u_char, safi_t);
extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t);
extern int
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id,
- u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi);
+ u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
+ u_char distance, safi_t safi);
extern int
rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
int index;
int table;
int metric;
+ u_int32_t mtu = 0;
void *dest;
void *gate;
if (tb[RTA_PRIORITY])
metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
+ if (tb[RTA_METRICS])
+ {
+ struct rtattr *mxrta[RTAX_MAX+1];
+
+ memset (mxrta, 0, sizeof mxrta);
+ netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
+ RTA_PAYLOAD(tb[RTA_METRICS]));
+
+ if (mxrta[RTAX_MTU])
+ mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
+ }
+
if (rtm->rtm_family == AF_INET)
{
struct prefix_ipv4 p;
if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index,
- vrf_id, table, metric, 0, SAFI_UNICAST);
+ vrf_id, table, metric, mtu, 0, SAFI_UNICAST);
else
{
/* This is a multipath route */
rib->distance = 0;
rib->flags = flags;
rib->metric = metric;
+ rib->mtu = mtu;
rib->vrf_id = vrf_id;
rib->table = table;
rib->nexthop_num = 0;
p.prefixlen = rtm->rtm_dst_len;
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id,
- table, metric, 0, SAFI_UNICAST);
+ table, metric, mtu, 0, SAFI_UNICAST);
}
#endif /* HAVE_IPV6 */
int index;
int table;
int metric;
+ u_int32_t mtu = 0;
void *dest;
void *gate;
if (tb[RTA_PREFSRC])
src = RTA_DATA (tb[RTA_PREFSRC]);
- if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY])
- metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
+ if (h->nlmsg_type == RTM_NEWROUTE)
+ {
+ if (tb[RTA_PRIORITY])
+ metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
+
+ if (tb[RTA_METRICS])
+ {
+ struct rtattr *mxrta[RTAX_MAX+1];
+
+ memset (mxrta, 0, sizeof mxrta);
+ netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
+ RTA_PAYLOAD(tb[RTA_METRICS]));
+
+ if (mxrta[RTAX_MTU])
+ mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
+ }
+ }
if (rtm->rtm_family == AF_INET)
{
{
if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id,
- table, metric, 0, SAFI_UNICAST);
+ table, metric, mtu, 0, SAFI_UNICAST);
else
{
/* This is a multipath route */
rib->distance = 0;
rib->flags = 0;
rib->metric = metric;
+ rib->mtu = mtu;
rib->vrf_id = vrf_id;
rib->table = table;
rib->nexthop_num = 0;
if (h->nlmsg_type == RTM_NEWROUTE)
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, vrf_id,
- table, metric, 0, SAFI_UNICAST);
+ table, metric, mtu, 0, SAFI_UNICAST);
else
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index,
vrf_id, table, SAFI_UNICAST);
addattr32(&req.n, sizeof req, RTA_TABLE, rib->table);
}
+ if (rib->mtu || rib->nexthop_mtu)
+ {
+ char buf[NL_PKT_BUF_SIZE];
+ struct rtattr *rta = (void *) buf;
+ u_int32_t mtu = rib->mtu;
+ if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu))
+ mtu = rib->nexthop_mtu;
+ rta->rta_type = RTA_METRICS;
+ rta->rta_len = RTA_LENGTH(0);
+ rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
+ addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
+ RTA_PAYLOAD (rta));
+ }
+
if (discard)
{
if (cmd == RTM_NEWROUTE)
zebra_deregister_rnh_static_nexthops(rib->vrf_id, nexthop->resolved, top);
nexthops_free(nexthop->resolved);
nexthop->resolved = NULL;
+ rib->nexthop_mtu = 0;
}
/* Skip nexthops that have been filtered out due to route-map */
}
resolved = 1;
}
+ if (resolved && set)
+ rib->nexthop_mtu = match->mtu;
return resolved;
}
else
rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src,
ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id,
- u_int32_t metric, u_char distance, safi_t safi)
+ u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
{
struct rib *rib;
struct rib *same = NULL;
rib->distance = distance;
rib->flags = flags;
rib->metric = metric;
+ rib->mtu = mtu;
rib->table = table_id;
rib->vrf_id = vrf_id;
rib->nexthop_num = 0;
);
zlog_debug
(
- "%s: metric == %u, distance == %u, flags == %u, status == %u",
+ "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u",
func,
rib->metric,
+ rib->mtu,
rib->distance,
rib->flags,
rib->status
rib->instance = 0;
rib->distance = si->distance;
rib->metric = 0;
+ rib->mtu = 0;
rib->vrf_id = si->vrf_id;
rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default;
rib->nexthop_num = 0;
int
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id,
- u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi)
+ u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
+ u_char distance, safi_t safi)
{
struct rib *rib;
struct rib *same = NULL;
rib->distance = distance;
rib->flags = flags;
rib->metric = metric;
+ rib->mtu = mtu;
rib->table = table_id;
rib->vrf_id = vrf_id;
rib->nexthop_num = 0;
vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric);
if (rib->tag)
vty_out (vty, ", tag %d", rib->tag);
+ if (rib->mtu)
+ vty_out (vty, ", mtu %u", rib->mtu);
if (rib->vrf_id != VRF_DEFAULT)
{
zvrf = vrf_info_lookup(rib->vrf_id);
SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG);
stream_putw(s, rib->tag);
}
+ SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU);
+ stream_putl (s, rib->mtu);
}
/* write real message flags value */
else
rib->tag = 0;
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
+ rib->mtu = stream_getl (s);
+ else
+ rib->mtu = 0;
+
/* Table */
rib->table = zvrf->table_id;
else
rib->tag = 0;
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
+ rib->mtu = stream_getl (s);
+ else
+ rib->mtu = 0;
+
/* Table */
rib->table = zvrf->table_id;
else
rib->tag = 0;
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
+ rib->mtu = stream_getl (s);
+ else
+ rib->mtu = 0;
+
/* VRF ID */
rib->vrf_id = zvrf->vrf_id;
rib->table = zvrf->table_id;