2 * IP MSDP packet helper
3 * Copyright (C) 2016 Cumulus Networks, Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <lib/network.h>
23 #include <lib/stream.h>
24 #include <lib/thread.h>
26 #include <lib/lib_errors.h>
29 #include "pim_instance.h"
31 #include "pim_errors.h"
34 #include "pim_msdp_packet.h"
35 #include "pim_msdp_socket.h"
37 static char *pim_msdp_pkt_type_dump(enum pim_msdp_tlv type
, char *buf
,
41 case PIM_MSDP_V4_SOURCE_ACTIVE
:
42 snprintf(buf
, buf_size
, "%s", "SA");
44 case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST
:
45 snprintf(buf
, buf_size
, "%s", "SA_REQ");
47 case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE
:
48 snprintf(buf
, buf_size
, "%s", "SA_RESP");
50 case PIM_MSDP_KEEPALIVE
:
51 snprintf(buf
, buf_size
, "%s", "KA");
53 case PIM_MSDP_RESERVED
:
54 snprintf(buf
, buf_size
, "%s", "RSVD");
56 case PIM_MSDP_TRACEROUTE_PROGRESS
:
57 snprintf(buf
, buf_size
, "%s", "TRACE_PROG");
59 case PIM_MSDP_TRACEROUTE_REPLY
:
60 snprintf(buf
, buf_size
, "%s", "TRACE_REPLY");
63 snprintf(buf
, buf_size
, "UNK-%d", type
);
68 static void pim_msdp_pkt_sa_dump_one(struct stream
*s
)
72 /* just throw away the three reserved bytes */
74 /* throw away the prefix length also */
77 memset(&sg
, 0, sizeof(sg
));
78 sg
.grp
.s_addr
= stream_get_ipv4(s
);
79 sg
.src
.s_addr
= stream_get_ipv4(s
);
81 zlog_debug(" sg %pSG", &sg
);
84 static void pim_msdp_pkt_sa_dump(struct stream
*s
)
86 const size_t header_length
= PIM_MSDP_SA_X_SIZE
- PIM_MSDP_HEADER_SIZE
;
87 size_t payload_length
;
90 struct in_addr rp
; /* Last RP address associated with this SA */
92 if (header_length
> STREAM_READABLE(s
)) {
93 zlog_err("BUG MSDP SA bad header (readable %zu expected %zu)",
94 STREAM_READABLE(s
), header_length
);
98 entry_cnt
= stream_getc(s
);
99 rp
.s_addr
= stream_get_ipv4(s
);
101 if (PIM_DEBUG_MSDP_PACKETS
) {
102 char rp_str
[INET_ADDRSTRLEN
];
103 pim_inet4_dump("<rp?>", rp
, rp_str
, sizeof(rp_str
));
104 zlog_debug(" entry_cnt %d rp %s", entry_cnt
, rp_str
);
107 payload_length
= (size_t)entry_cnt
* PIM_MSDP_SA_ONE_ENTRY_SIZE
;
108 if (payload_length
> STREAM_READABLE(s
)) {
109 zlog_err("BUG MSDP SA bad length (readable %zu expected %zu)",
110 STREAM_READABLE(s
), payload_length
);
115 for (i
= 0; i
< entry_cnt
; ++i
) {
116 pim_msdp_pkt_sa_dump_one(s
);
120 static void pim_msdp_pkt_dump(struct pim_msdp_peer
*mp
, int type
, int len
,
121 bool rx
, struct stream
*s
)
123 char type_str
[PIM_MSDP_PKT_TYPE_STRLEN
];
125 pim_msdp_pkt_type_dump(type
, type_str
, sizeof(type_str
));
127 zlog_debug("MSDP peer %s pkt %s type %s len %d", mp
->key_str
,
128 rx
? "rx" : "tx", type_str
, len
);
134 if (len
< PIM_MSDP_HEADER_SIZE
) {
135 zlog_err("invalid MSDP header length");
140 case PIM_MSDP_V4_SOURCE_ACTIVE
:
141 pim_msdp_pkt_sa_dump(s
);
147 /* Check file descriptor whether connect is established. */
148 static void pim_msdp_connect_check(struct pim_msdp_peer
*mp
)
154 if (mp
->state
!= PIM_MSDP_CONNECTING
) {
155 /* if we are here it means we are not in a connecting or
157 * for now treat this as a fatal error */
158 pim_msdp_peer_reset_tcp_conn(mp
, "invalid-state");
162 PIM_MSDP_PEER_READ_OFF(mp
);
163 PIM_MSDP_PEER_WRITE_OFF(mp
);
165 /* Check file descriptor. */
166 slen
= sizeof(status
);
167 ret
= getsockopt(mp
->fd
, SOL_SOCKET
, SO_ERROR
, (void *)&status
, &slen
);
169 /* If getsockopt is fail, this is fatal error. */
171 flog_err_sys(EC_LIB_SOCKET
,
172 "can't get sockopt for nonblocking connect");
173 pim_msdp_peer_reset_tcp_conn(mp
, "connect-failed");
177 /* When status is 0 then TCP connection is established. */
178 if (PIM_DEBUG_MSDP_INTERNAL
) {
179 zlog_debug("MSDP peer %s pim_connect_check %s", mp
->key_str
,
180 status
? "fail" : "success");
183 pim_msdp_peer_established(mp
);
185 pim_msdp_peer_reset_tcp_conn(mp
, "connect-failed");
189 static void pim_msdp_pkt_delete(struct pim_msdp_peer
*mp
)
191 stream_free(stream_fifo_pop(mp
->obuf
));
194 static void pim_msdp_pkt_add(struct pim_msdp_peer
*mp
, struct stream
*s
)
196 stream_fifo_push(mp
->obuf
, s
);
199 static void pim_msdp_write_proceed_actions(struct pim_msdp_peer
*mp
)
201 if (stream_fifo_head(mp
->obuf
)) {
202 PIM_MSDP_PEER_WRITE_ON(mp
);
206 void pim_msdp_write(struct thread
*thread
)
208 struct pim_msdp_peer
*mp
;
211 enum pim_msdp_tlv type
;
214 int work_max_cnt
= 100;
216 mp
= THREAD_ARG(thread
);
219 if (PIM_DEBUG_MSDP_INTERNAL
) {
220 zlog_debug("MSDP peer %s pim_msdp_write", mp
->key_str
);
226 /* check if TCP connection is established */
227 if (mp
->state
!= PIM_MSDP_ESTABLISHED
) {
228 pim_msdp_connect_check(mp
);
232 s
= stream_fifo_head(mp
->obuf
);
234 pim_msdp_write_proceed_actions(mp
);
238 /* Nonblocking write until TCP output buffer is full */
242 /* Number of bytes to be sent */
243 writenum
= stream_get_endp(s
) - stream_get_getp(s
);
245 /* Call write() system call */
246 num
= write(mp
->fd
, stream_pnt(s
), writenum
);
248 /* write failed either retry needed or error */
249 if (ERRNO_IO_RETRY(errno
)) {
250 if (PIM_DEBUG_MSDP_INTERNAL
) {
252 "MSDP peer %s pim_msdp_write io retry",
258 pim_msdp_peer_reset_tcp_conn(mp
, "pkt-tx-failed");
262 if (num
!= writenum
) {
264 stream_forward_getp(s
, num
);
265 if (PIM_DEBUG_MSDP_INTERNAL
) {
267 "MSDP peer %s pim_msdp_partial_write",
273 /* Retrieve msdp packet type. */
274 stream_set_getp(s
, 0);
275 type
= stream_getc(s
);
276 len
= stream_getw(s
);
278 case PIM_MSDP_KEEPALIVE
:
281 case PIM_MSDP_V4_SOURCE_ACTIVE
:
284 case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST
:
285 case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE
:
286 case PIM_MSDP_RESERVED
:
287 case PIM_MSDP_TRACEROUTE_PROGRESS
:
288 case PIM_MSDP_TRACEROUTE_REPLY
:
291 if (PIM_DEBUG_MSDP_PACKETS
) {
292 pim_msdp_pkt_dump(mp
, type
, len
, false /*rx*/, s
);
295 /* packet sent delete it. */
296 pim_msdp_pkt_delete(mp
);
299 /* may need to pause if we have done too much work in this
301 if (work_cnt
>= work_max_cnt
) {
304 } while ((s
= stream_fifo_head(mp
->obuf
)) != NULL
);
305 pim_msdp_write_proceed_actions(mp
);
307 if (PIM_DEBUG_MSDP_INTERNAL
) {
308 zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets",
309 mp
->key_str
, work_cnt
);
313 static void pim_msdp_pkt_send(struct pim_msdp_peer
*mp
, struct stream
*s
)
315 /* Add packet to the end of list. */
316 pim_msdp_pkt_add(mp
, s
);
318 PIM_MSDP_PEER_WRITE_ON(mp
);
321 void pim_msdp_pkt_ka_tx(struct pim_msdp_peer
*mp
)
325 if (mp
->state
!= PIM_MSDP_ESTABLISHED
) {
326 /* don't tx anything unless a session is established */
329 s
= stream_new(PIM_MSDP_KA_TLV_MAX_SIZE
);
330 stream_putc(s
, PIM_MSDP_KEEPALIVE
);
331 stream_putw(s
, PIM_MSDP_KA_TLV_MAX_SIZE
);
333 pim_msdp_pkt_send(mp
, s
);
336 static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_instance
*pim
,
337 struct pim_msdp_peer
*mp
)
341 if (mp
->state
!= PIM_MSDP_ESTABLISHED
) {
342 /* don't tx anything unless a session is established */
345 s
= stream_dup(pim
->msdp
.work_obuf
);
347 pim_msdp_pkt_send(mp
, s
);
348 mp
->flags
|= PIM_MSDP_PEERF_SA_JUST_SENT
;
352 /* push the stream into the obuf fifo of all the peers */
353 static void pim_msdp_pkt_sa_push(struct pim_instance
*pim
,
354 struct pim_msdp_peer
*mp
)
356 struct listnode
*mpnode
;
359 pim_msdp_pkt_sa_push_to_one_peer(pim
, mp
);
361 for (ALL_LIST_ELEMENTS_RO(pim
->msdp
.peer_list
, mpnode
, mp
)) {
362 if (PIM_DEBUG_MSDP_INTERNAL
) {
363 zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push",
366 pim_msdp_pkt_sa_push_to_one_peer(pim
, mp
);
371 static int pim_msdp_pkt_sa_fill_hdr(struct pim_instance
*pim
, int local_cnt
,
376 stream_reset(pim
->msdp
.work_obuf
);
377 curr_tlv_ecnt
= local_cnt
> PIM_MSDP_SA_MAX_ENTRY_CNT
378 ? PIM_MSDP_SA_MAX_ENTRY_CNT
380 local_cnt
-= curr_tlv_ecnt
;
381 stream_putc(pim
->msdp
.work_obuf
, PIM_MSDP_V4_SOURCE_ACTIVE
);
382 stream_putw(pim
->msdp
.work_obuf
,
383 PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt
));
384 stream_putc(pim
->msdp
.work_obuf
, curr_tlv_ecnt
);
385 stream_put_ipv4(pim
->msdp
.work_obuf
, rp
.s_addr
);
390 static void pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa
*sa
)
392 stream_put3(sa
->pim
->msdp
.work_obuf
, 0 /* reserved */);
393 stream_putc(sa
->pim
->msdp
.work_obuf
, 32 /* sprefix len */);
394 stream_put_ipv4(sa
->pim
->msdp
.work_obuf
, sa
->sg
.grp
.s_addr
);
395 stream_put_ipv4(sa
->pim
->msdp
.work_obuf
, sa
->sg
.src
.s_addr
);
398 static void pim_msdp_pkt_sa_gen(struct pim_instance
*pim
,
399 struct pim_msdp_peer
*mp
)
401 struct listnode
*sanode
;
402 struct pim_msdp_sa
*sa
;
404 int local_cnt
= pim
->msdp
.local_cnt
;
407 if (PIM_DEBUG_MSDP_INTERNAL
) {
408 zlog_debug(" sa gen %d", local_cnt
);
411 local_cnt
= pim_msdp_pkt_sa_fill_hdr(pim
, local_cnt
,
412 pim
->msdp
.originator_id
);
414 for (ALL_LIST_ELEMENTS_RO(pim
->msdp
.sa_list
, sanode
, sa
)) {
415 if (!(sa
->flags
& PIM_MSDP_SAF_LOCAL
)) {
416 /* current implementation of MSDP is for anycast i.e.
418 * no re-forwarding of SAs that we learnt from other
422 /* add sa into scratch pad */
423 pim_msdp_pkt_sa_fill_one(sa
);
425 if (sa_count
>= PIM_MSDP_SA_MAX_ENTRY_CNT
) {
426 pim_msdp_pkt_sa_push(pim
, mp
);
429 if (PIM_DEBUG_MSDP_INTERNAL
) {
430 zlog_debug(" sa gen for remainder %d",
433 local_cnt
= pim_msdp_pkt_sa_fill_hdr(
434 pim
, local_cnt
, pim
->msdp
.originator_id
);
439 pim_msdp_pkt_sa_push(pim
, mp
);
444 static void pim_msdp_pkt_sa_tx_done(struct pim_instance
*pim
)
446 struct listnode
*mpnode
;
447 struct pim_msdp_peer
*mp
;
449 /* if SA were sent to the peers we restart ka timer and avoid
450 * unnecessary ka noise */
451 for (ALL_LIST_ELEMENTS_RO(pim
->msdp
.peer_list
, mpnode
, mp
)) {
452 if (mp
->flags
& PIM_MSDP_PEERF_SA_JUST_SENT
) {
453 mp
->flags
&= ~PIM_MSDP_PEERF_SA_JUST_SENT
;
454 pim_msdp_peer_pkt_txed(mp
);
459 void pim_msdp_pkt_sa_tx(struct pim_instance
*pim
)
461 pim_msdp_pkt_sa_gen(pim
, NULL
/* mp */);
462 pim_msdp_pkt_sa_tx_done(pim
);
465 void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa
*sa
)
467 pim_msdp_pkt_sa_fill_hdr(sa
->pim
, 1 /* cnt */, sa
->rp
);
468 pim_msdp_pkt_sa_fill_one(sa
);
469 pim_msdp_pkt_sa_push(sa
->pim
, NULL
);
470 pim_msdp_pkt_sa_tx_done(sa
->pim
);
473 /* when a connection is first established we push all SAs immediately */
474 void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer
*mp
)
476 pim_msdp_pkt_sa_gen(mp
->pim
, mp
);
477 pim_msdp_pkt_sa_tx_done(mp
->pim
);
480 void pim_msdp_pkt_sa_tx_one_to_one_peer(struct pim_msdp_peer
*mp
,
481 struct in_addr rp
, pim_sgaddr sg
)
483 struct pim_msdp_sa sa
;
485 /* Fills the SA header. */
486 pim_msdp_pkt_sa_fill_hdr(mp
->pim
, 1, rp
);
488 /* Fills the message contents. */
491 pim_msdp_pkt_sa_fill_one(&sa
);
493 /* Pushes the message. */
494 pim_msdp_pkt_sa_push(sa
.pim
, mp
);
495 pim_msdp_pkt_sa_tx_done(sa
.pim
);
498 static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer
*mp
)
500 pim_msdp_peer_reset_tcp_conn(mp
, "invalid-pkt-rx");
503 static void pim_msdp_pkt_ka_rx(struct pim_msdp_peer
*mp
, int len
)
506 if (len
!= PIM_MSDP_KA_TLV_MAX_SIZE
) {
507 pim_msdp_pkt_rxed_with_fatal_error(mp
);
510 pim_msdp_peer_pkt_rxed(mp
);
513 static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer
*mp
, struct in_addr rp
)
517 struct listnode
*peer_node
;
518 struct pim_msdp_peer
*peer
;
520 /* just throw away the three reserved bytes */
521 stream_get3(mp
->ibuf
);
522 prefix_len
= stream_getc(mp
->ibuf
);
524 memset(&sg
, 0, sizeof(sg
));
525 sg
.grp
.s_addr
= stream_get_ipv4(mp
->ibuf
);
526 sg
.src
.s_addr
= stream_get_ipv4(mp
->ibuf
);
528 if (prefix_len
!= IPV4_MAX_BITLEN
) {
529 /* ignore SA update if the prefix length is not 32 */
530 flog_err(EC_PIM_MSDP_PACKET
,
531 "rxed sa update with invalid prefix length %d",
535 if (PIM_DEBUG_MSDP_PACKETS
) {
536 zlog_debug(" sg %pSG", &sg
);
538 pim_msdp_sa_ref(mp
->pim
, mp
, &sg
, rp
);
540 /* Forwards the SA to the peers that are not in the RPF to the RP nor in
541 * the same mesh group as the peer from which we received the message.
542 * If the message group is not set, i.e. "default", then we assume that
543 * the message must be forwarded.*/
544 for (ALL_LIST_ELEMENTS_RO(mp
->pim
->msdp
.peer_list
, peer_node
, peer
)) {
545 /* Not a RPF peer, so skip it. */
546 if (pim_msdp_peer_rpf_check(peer
, rp
))
548 /* Don't forward inside the meshed group. */
549 if ((mp
->flags
& PIM_MSDP_PEERF_IN_GROUP
)
550 && strcmp(mp
->mesh_group_name
, peer
->mesh_group_name
) == 0)
553 pim_msdp_pkt_sa_tx_one_to_one_peer(peer
, rp
, sg
);
557 static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer
*mp
, int len
)
561 struct in_addr rp
; /* Last RP address associated with this SA */
565 if (len
< PIM_MSDP_SA_TLV_MIN_SIZE
) {
566 pim_msdp_pkt_rxed_with_fatal_error(mp
);
570 entry_cnt
= stream_getc(mp
->ibuf
);
571 /* some vendors include the actual multicast data in the tlv (at the
572 * end). we will ignore such data. in the future we may consider pushing
575 if (len
< PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt
)) {
576 pim_msdp_pkt_rxed_with_fatal_error(mp
);
579 rp
.s_addr
= stream_get_ipv4(mp
->ibuf
);
581 if (PIM_DEBUG_MSDP_PACKETS
) {
582 char rp_str
[INET_ADDRSTRLEN
];
583 pim_inet4_dump("<rp?>", rp
, rp_str
, sizeof(rp_str
));
584 zlog_debug(" entry_cnt %d rp %s", entry_cnt
, rp_str
);
587 pim_msdp_peer_pkt_rxed(mp
);
589 if (!pim_msdp_peer_rpf_check(mp
, rp
)) {
590 /* if peer-RPF check fails don't process the packet any further
592 if (PIM_DEBUG_MSDP_PACKETS
) {
593 zlog_debug(" peer RPF check failed");
598 /* update SA cache */
599 for (i
= 0; i
< entry_cnt
; ++i
) {
600 pim_msdp_pkt_sa_rx_one(mp
, rp
);
604 static void pim_msdp_pkt_rx(struct pim_msdp_peer
*mp
)
606 enum pim_msdp_tlv type
;
609 /* re-read type and len */
610 type
= stream_getc_from(mp
->ibuf
, 0);
611 len
= stream_getw_from(mp
->ibuf
, 1);
612 if (len
< PIM_MSDP_HEADER_SIZE
) {
613 pim_msdp_pkt_rxed_with_fatal_error(mp
);
617 if (len
> PIM_MSDP_SA_TLV_MAX_SIZE
) {
618 /* if tlv size if greater than max just ignore the tlv */
622 if (PIM_DEBUG_MSDP_PACKETS
) {
623 pim_msdp_pkt_dump(mp
, type
, len
, true /*rx*/, NULL
/*s*/);
627 case PIM_MSDP_KEEPALIVE
:
628 pim_msdp_pkt_ka_rx(mp
, len
);
630 case PIM_MSDP_V4_SOURCE_ACTIVE
:
632 pim_msdp_pkt_sa_rx(mp
, len
);
634 case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST
:
635 case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE
:
636 case PIM_MSDP_RESERVED
:
637 case PIM_MSDP_TRACEROUTE_PROGRESS
:
638 case PIM_MSDP_TRACEROUTE_REPLY
:
644 /* pim msdp read utility function. */
645 static int pim_msdp_read_packet(struct pim_msdp_peer
*mp
)
652 old_endp
= stream_get_endp(mp
->ibuf
);
653 readsize
= mp
->packet_size
- old_endp
;
658 /* Read packet from fd */
659 nbytes
= stream_read_try(mp
->ibuf
, mp
->fd
, readsize
);
660 new_endp
= stream_get_endp(mp
->ibuf
);
662 if (PIM_DEBUG_MSDP_INTERNAL
) {
663 zlog_debug("MSDP peer %s read failed %d", mp
->key_str
,
667 if (PIM_DEBUG_MSDP_INTERNAL
) {
669 "MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d",
670 mp
->key_str
, old_endp
, new_endp
);
672 /* transient error retry */
675 pim_msdp_pkt_rxed_with_fatal_error(mp
);
680 if (PIM_DEBUG_MSDP_INTERNAL
) {
681 zlog_debug("MSDP peer %s read failed %d", mp
->key_str
,
684 pim_msdp_peer_reset_tcp_conn(mp
, "peer-down");
688 /* We read partial packet. */
689 if (stream_get_endp(mp
->ibuf
) != mp
->packet_size
) {
690 if (PIM_DEBUG_MSDP_INTERNAL
) {
692 "MSDP peer %s read partial len %d old_endp %d new_endp %d",
693 mp
->key_str
, mp
->packet_size
, old_endp
,
702 void pim_msdp_read(struct thread
*thread
)
704 struct pim_msdp_peer
*mp
;
708 mp
= THREAD_ARG(thread
);
711 if (PIM_DEBUG_MSDP_INTERNAL
) {
712 zlog_debug("MSDP peer %s pim_msdp_read", mp
->key_str
);
719 /* check if TCP connection is established */
720 if (mp
->state
!= PIM_MSDP_ESTABLISHED
) {
721 pim_msdp_connect_check(mp
);
725 PIM_MSDP_PEER_READ_ON(mp
);
727 if (!mp
->packet_size
) {
728 mp
->packet_size
= PIM_MSDP_HEADER_SIZE
;
731 if (stream_get_endp(mp
->ibuf
) < PIM_MSDP_HEADER_SIZE
) {
732 /* start by reading the TLV header */
733 rc
= pim_msdp_read_packet(mp
);
737 /* Find TLV type and len */
738 stream_getc(mp
->ibuf
);
739 len
= stream_getw(mp
->ibuf
);
740 if (len
< PIM_MSDP_HEADER_SIZE
) {
741 pim_msdp_pkt_rxed_with_fatal_error(mp
);
746 * Handle messages with longer than expected TLV size: resize
747 * the stream to handle reading the whole message.
749 * RFC 3618 Section 12. 'Packet Formats':
750 * > ... If an implementation receives a TLV whose length
751 * > exceeds the maximum TLV length specified below, the TLV
752 * > SHOULD be accepted. Any additional data, including possible
753 * > next TLV's in the same message, SHOULD be ignored, and the
754 * > MSDP session should not be reset. ...
756 if (len
> PIM_MSDP_SA_TLV_MAX_SIZE
) {
757 /* Check if the current buffer is big enough. */
758 if (mp
->ibuf
->size
< len
) {
759 if (PIM_DEBUG_MSDP_PACKETS
)
761 "MSDP peer %s sent TLV with unexpected large length (%d bytes)",
764 stream_resize_inplace(&mp
->ibuf
, len
);
768 /* read complete TLV */
769 mp
->packet_size
= len
;
772 rc
= pim_msdp_read_packet(mp
);
778 /* reset input buffers and get ready for the next packet */
780 stream_reset(mp
->ibuf
);