stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
sizep = stream_get_endp (s);
stream_putw (s, 0); /* Marker: Attribute length. */
- stream_putw (s, afi); /* AFI */
- stream_putc (s, safi); /* SAFI */
+
+ stream_putw (s, afi);
+ stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
/* Nexthop */
switch (nh_afi)
case AFI_IP:
switch (safi)
{
- case SAFI_UNICAST:
case SAFI_MULTICAST:
bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
stream_putc (s, 4);
case SAFI_MPLS_VPN:
bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
stream_putc (s, 12);
- stream_putl (s, 0);
+ stream_putl (s, 0); /* RD = 0, per RFC */
stream_putl (s, 0);
stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
break;
+ case SAFI_UNICAST: /* invalid for IPv4 */
default:
break;
}
if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
}
+ break;
+ case SAFI_MPLS_VPN:
+ {
+ struct attr_extra *attre = attr->extra;
+
+ assert (attr->extra);
+ if (attre->mp_nexthop_len == 16) {
+ stream_putc (s, 24);
+ stream_putl (s, 0); /* RD = 0, per RFC */
+ stream_putl (s, 0);
+ stream_put (s, &attre->mp_nexthop_global, 16);
+ } else if (attre->mp_nexthop_len == 32) {
+ stream_putc (s, 48);
+ stream_putl (s, 0); /* RD = 0, per RFC */
+ stream_putl (s, 0);
+ stream_put (s, &attre->mp_nexthop_global, 16);
+ stream_putl (s, 0); /* RD = 0, per RFC */
+ stream_putl (s, 0);
+ stream_put (s, &attre->mp_nexthop_local, 16);
+ }
+ }
+ break;
default:
break;
}
u_char *tag, int addpath_encode,
u_int32_t addpath_tx_id)
{
- switch (safi)
+ if (safi == SAFI_MPLS_VPN)
{
- case SAFI_MPLS_VPN:
- /* addpath TX ID */
if (addpath_encode)
stream_putl(s, addpath_tx_id);
-
/* Tag, RD, Prefix write. */
stream_putc (s, p->prefixlen + 88);
stream_put (s, tag, 3);
stream_put (s, prd->val, 8);
stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
- break;
- default:
- /* Prefix write. */
- stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
- break;
}
+ else
+ stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
+}
+
+size_t
+bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
+{
+ int size = PSIZE (p->prefixlen);
+ if (safi == SAFI_MPLS_VPN)
+ size += 88;
+ return size;
}
void
int send_as4_path = 0;
int send_as4_aggregator = 0;
int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
- size_t mpattrlen_pos = 0;
if (! bgp)
bgp = peer->bgp;
if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
!peer_cap_enhe(peer)))
{
+ size_t mpattrlen_pos = 0;
+
mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi,
(peer_cap_enhe(peer) ? AFI_IP6 : afi),
vecarr, attr);
send_as4_path = 1; /* we'll do this later, at the correct place */
/* Nexthop attribute. */
- if (afi == AFI_IP && !peer_cap_enhe(peer))
+ if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer))
{
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
{
stream_putw (s, 0); /* Length of this attribute. */
stream_putw (s, afi);
- safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
- stream_putc (s, safi);
+ stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
return attrlen_pnt;
}
void
bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
{
- bgp_size_t size;
-
- /* Set MP attribute length. Don't count the (2) bytes used to encode
- the attr length */
- size = stream_get_endp (s) - attrlen_pnt - 2;
- stream_putw_at (s, attrlen_pnt, size);
+ bgp_packet_mpattr_end (s, attrlen_pnt);
}
/* Initialization of attribute. */
decode_rd_ip (pnt + 5, &rd_ip);
break;
- case RD_TYPE_EOI:
- break;
-
- default:
- zlog_err ("Invalid RD type %d", type);
- return -1;
- }
+ default:
+ zlog_err ("Unknown RD type %d", type);
+ break; /* just report */
+ }
p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8;
memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES,
snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
return buf;
}
- else if (type == RD_TYPE_EOI)
- {
- snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
- pnt[1], /* LHI */
- pnt[2], pnt[3], pnt[4], pnt[5], pnt[6], pnt[7]); /* MAC */
- return buf;
- }
-
return NULL;
}
space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
BGP_MAX_PACKET_SIZE_OVERFLOW;
- space_needed = BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen);
+ space_needed = BGP_NLRI_LENGTH +
+ bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
/* When remaining space can't include NLRI and it's length. */
if (space_remaining < space_needed)
/* If packet is empty, set attribute. */
if (stream_empty (s))
{
+ struct prefix_rd *prd = NULL;
+ u_char *tag = NULL;
struct peer *from = NULL;
+ if (rn->prn)
+ prd = (struct prefix_rd *) &rn->prn->p;
if (binfo)
- from = binfo->peer;
+ {
+ from = binfo->peer;
+ if (binfo->extra)
+ tag = binfo->extra->tag;
+ }
/* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
* one byte message type.
/* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
total_attr_len = bgp_packet_attribute (NULL, peer, s,
adv->baa->attr, &vecarr,
- NULL, afi, safi,
- from, NULL, NULL, 0, 0);
+ &rn->p, afi, safi,
+ from, prd, tag, 0, 0);
space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
BGP_MAX_PACKET_SIZE_OVERFLOW;