]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_msdp_packet.c
*: reindent
[mirror_frr.git] / pimd / pim_msdp_packet.c
CommitLineData
2a333e0f 1/*
2 * IP MSDP packet helper
3 * Copyright (C) 2016 Cumulus Networks, Inc.
4 *
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.
9 *
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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; see the file COPYING; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 * MA 02110-1301 USA
19 */
20#include <zebra.h>
21
22#include <lib/log.h>
23#include <lib/network.h>
24#include <lib/stream.h>
25#include <lib/thread.h>
3c72d654 26#include <lib/vty.h>
2a333e0f 27
28#include "pimd.h"
29#include "pim_str.h"
30
31#include "pim_msdp.h"
32#include "pim_msdp_packet.h"
33#include "pim_msdp_socket.h"
34
ac4d0be5 35static char *pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf,
36 int buf_size)
2a333e0f 37{
ac4d0be5 38 switch (type) {
39 case PIM_MSDP_V4_SOURCE_ACTIVE:
40 snprintf(buf, buf_size, "%s", "SA");
41 break;
42 case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST:
43 snprintf(buf, buf_size, "%s", "SA_REQ");
44 break;
45 case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE:
46 snprintf(buf, buf_size, "%s", "SA_RESP");
47 break;
48 case PIM_MSDP_KEEPALIVE:
49 snprintf(buf, buf_size, "%s", "KA");
50 break;
51 case PIM_MSDP_RESERVED:
52 snprintf(buf, buf_size, "%s", "RSVD");
53 break;
54 case PIM_MSDP_TRACEROUTE_PROGRESS:
55 snprintf(buf, buf_size, "%s", "TRACE_PROG");
56 break;
57 case PIM_MSDP_TRACEROUTE_REPLY:
58 snprintf(buf, buf_size, "%s", "TRACE_REPLY");
59 break;
60 default:
61 snprintf(buf, buf_size, "UNK-%d", type);
62 }
63 return buf;
2a333e0f 64}
65
ac4d0be5 66static void pim_msdp_pkt_sa_dump_one(struct stream *s)
15ad0c71 67{
ac4d0be5 68 struct prefix_sg sg;
15ad0c71 69
ac4d0be5 70 /* just throw away the three reserved bytes */
71 stream_get3(s);
72 /* throw away the prefix length also */
73 stream_getc(s);
15ad0c71 74
ac4d0be5 75 memset(&sg, 0, sizeof(struct prefix_sg));
76 sg.grp.s_addr = stream_get_ipv4(s);
77 sg.src.s_addr = stream_get_ipv4(s);
15ad0c71 78
ac4d0be5 79 zlog_debug(" sg %s", pim_str_sg_dump(&sg));
15ad0c71 80}
81
ac4d0be5 82static void pim_msdp_pkt_sa_dump(struct stream *s)
15ad0c71 83{
ac4d0be5 84 int entry_cnt;
85 int i;
86 struct in_addr rp; /* Last RP address associated with this SA */
87
88 entry_cnt = stream_getc(s);
89 rp.s_addr = stream_get_ipv4(s);
90
91 if (PIM_DEBUG_MSDP_PACKETS) {
92 char rp_str[INET_ADDRSTRLEN];
93 pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str));
94 zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str);
95 }
96
97 /* dump SAs */
98 for (i = 0; i < entry_cnt; ++i) {
99 pim_msdp_pkt_sa_dump_one(s);
100 }
15ad0c71 101}
102
ac4d0be5 103static void pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len,
104 bool rx, struct stream *s)
2a333e0f 105{
ac4d0be5 106 char type_str[PIM_MSDP_PKT_TYPE_STRLEN];
2a333e0f 107
ac4d0be5 108 pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str));
2a333e0f 109
ac4d0be5 110 zlog_debug("MSDP peer %s pkt %s type %s len %d", mp->key_str,
111 rx ? "rx" : "tx", type_str, len);
15ad0c71 112
ac4d0be5 113 if (!s) {
114 return;
115 }
15ad0c71 116
ac4d0be5 117 switch (type) {
118 case PIM_MSDP_V4_SOURCE_ACTIVE:
119 pim_msdp_pkt_sa_dump(s);
120 break;
121 default:;
122 }
2a333e0f 123}
124
125/* Check file descriptor whether connect is established. */
ac4d0be5 126static void pim_msdp_connect_check(struct pim_msdp_peer *mp)
2a333e0f 127{
ac4d0be5 128 int status;
129 socklen_t slen;
130 int ret;
131
132 if (mp->state != PIM_MSDP_CONNECTING) {
133 /* if we are here it means we are not in a connecting or
134 * established state
135 * for now treat this as a fatal error */
136 pim_msdp_peer_reset_tcp_conn(mp, "invalid-state");
137 return;
138 }
139
140 PIM_MSDP_PEER_READ_OFF(mp);
141 PIM_MSDP_PEER_WRITE_OFF(mp);
142
143 /* Check file descriptor. */
144 slen = sizeof(status);
145 ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen);
146
147 /* If getsockopt is fail, this is fatal error. */
148 if (ret < 0) {
149 zlog_err("can't get sockopt for nonblocking connect");
150 pim_msdp_peer_reset_tcp_conn(mp, "connect-failed");
151 return;
152 }
153
154 /* When status is 0 then TCP connection is established. */
155 if (PIM_DEBUG_MSDP_INTERNAL) {
156 zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str,
157 status ? "fail" : "success");
158 }
159 if (status == 0) {
160 pim_msdp_peer_established(mp);
161 } else {
162 pim_msdp_peer_reset_tcp_conn(mp, "connect-failed");
163 }
2a333e0f 164}
165
ac4d0be5 166static void pim_msdp_pkt_delete(struct pim_msdp_peer *mp)
2a333e0f 167{
ac4d0be5 168 stream_free(stream_fifo_pop(mp->obuf));
2a333e0f 169}
170
ac4d0be5 171static void pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s)
3c72d654 172{
ac4d0be5 173 stream_fifo_push(mp->obuf, s);
3c72d654 174}
175
ac4d0be5 176static void pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp)
2a333e0f 177{
ac4d0be5 178 if (stream_fifo_head(mp->obuf)) {
179 PIM_MSDP_PEER_WRITE_ON(mp);
180 }
2a333e0f 181}
182
ac4d0be5 183int pim_msdp_write(struct thread *thread)
2a333e0f 184{
ac4d0be5 185 struct pim_msdp_peer *mp;
186 struct stream *s;
187 int num;
188 enum pim_msdp_tlv type;
189 int len;
190 int work_cnt = 0;
191 int work_max_cnt = 100;
192
193 mp = THREAD_ARG(thread);
194 mp->t_write = NULL;
195
196 if (PIM_DEBUG_MSDP_INTERNAL) {
197 zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str);
198 }
199 if (mp->fd < 0) {
200 return -1;
201 }
202
203 /* check if TCP connection is established */
204 if (mp->state != PIM_MSDP_ESTABLISHED) {
205 pim_msdp_connect_check(mp);
206 return 0;
207 }
208
209 s = stream_fifo_head(mp->obuf);
210 if (!s) {
211 pim_msdp_write_proceed_actions(mp);
212 return 0;
213 }
214
215 sockopt_cork(mp->fd, 1);
216
217 /* Nonblocking write until TCP output buffer is full */
218 do {
219 int writenum;
220
221 /* Number of bytes to be sent */
222 writenum = stream_get_endp(s) - stream_get_getp(s);
223
224 /* Call write() system call */
225 num = write(mp->fd, STREAM_PNT(s), writenum);
226 if (num < 0) {
227 /* write failed either retry needed or error */
228 if (ERRNO_IO_RETRY(errno)) {
229 if (PIM_DEBUG_MSDP_INTERNAL) {
230 zlog_debug(
231 "MSDP peer %s pim_msdp_write io retry",
232 mp->key_str);
233 }
234 break;
235 }
236
237 pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed");
238 return 0;
239 }
240
241 if (num != writenum) {
242 /* Partial write */
243 stream_forward_getp(s, num);
244 if (PIM_DEBUG_MSDP_INTERNAL) {
245 zlog_debug(
246 "MSDP peer %s pim_msdp_partial_write",
247 mp->key_str);
248 }
249 break;
250 }
251
252 /* Retrieve msdp packet type. */
253 stream_set_getp(s, 0);
254 type = stream_getc(s);
255 len = stream_getw(s);
256 switch (type) {
257 case PIM_MSDP_KEEPALIVE:
258 mp->ka_tx_cnt++;
259 break;
260 case PIM_MSDP_V4_SOURCE_ACTIVE:
261 mp->sa_tx_cnt++;
262 break;
263 default:;
264 }
265 if (PIM_DEBUG_MSDP_PACKETS) {
266 pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s);
267 }
268
269 /* packet sent delete it. */
270 pim_msdp_pkt_delete(mp);
271
272 ++work_cnt;
273 /* may need to pause if we have done too much work in this
274 * loop */
275 if (work_cnt >= work_max_cnt) {
276 break;
277 }
278 } while ((s = stream_fifo_head(mp->obuf)) != NULL);
279 pim_msdp_write_proceed_actions(mp);
280
281 sockopt_cork(mp->fd, 0);
282
283 if (PIM_DEBUG_MSDP_INTERNAL) {
284 zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets",
285 mp->key_str, work_cnt);
286 }
287
288 return 0;
2a333e0f 289}
290
ac4d0be5 291static void pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s)
2a333e0f 292{
ac4d0be5 293 /* Add packet to the end of list. */
294 pim_msdp_pkt_add(mp, s);
2a333e0f 295
ac4d0be5 296 PIM_MSDP_PEER_WRITE_ON(mp);
2a333e0f 297}
298
ac4d0be5 299void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp)
2a333e0f 300{
ac4d0be5 301 struct stream *s;
2a333e0f 302
ac4d0be5 303 if (mp->state != PIM_MSDP_ESTABLISHED) {
304 /* don't tx anything unless a session is established */
305 return;
306 }
307 s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE);
308 stream_putc(s, PIM_MSDP_KEEPALIVE);
309 stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE);
2a333e0f 310
ac4d0be5 311 pim_msdp_pkt_send(mp, s);
2a333e0f 312}
313
ac4d0be5 314static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp)
3c72d654 315{
ac4d0be5 316 struct stream *s;
317
318 if (mp->state != PIM_MSDP_ESTABLISHED) {
319 /* don't tx anything unless a session is established */
320 return;
321 }
322 s = stream_dup(msdp->work_obuf);
323 if (s) {
324 pim_msdp_pkt_send(mp, s);
325 mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT;
326 }
3c72d654 327}
328
329/* push the stream into the obuf fifo of all the peers */
ac4d0be5 330static void pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp)
3c72d654 331{
ac4d0be5 332 struct listnode *mpnode;
333
334 if (mp) {
335 pim_msdp_pkt_sa_push_to_one_peer(mp);
336 } else {
337 for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
338 if (PIM_DEBUG_MSDP_INTERNAL) {
339 zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push",
340 mp->key_str);
341 }
342 pim_msdp_pkt_sa_push_to_one_peer(mp);
343 }
344 }
3c72d654 345}
346
ac4d0be5 347static int pim_msdp_pkt_sa_fill_hdr(int local_cnt)
3c72d654 348{
ac4d0be5 349 int curr_tlv_ecnt;
350
351 stream_reset(msdp->work_obuf);
352 curr_tlv_ecnt = local_cnt > PIM_MSDP_SA_MAX_ENTRY_CNT
353 ? PIM_MSDP_SA_MAX_ENTRY_CNT
354 : local_cnt;
355 local_cnt -= curr_tlv_ecnt;
356 stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE);
357 stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt));
358 stream_putc(msdp->work_obuf, curr_tlv_ecnt);
359 stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr);
360
361 return local_cnt;
3c72d654 362}
363
ac4d0be5 364static void pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa)
3c72d654 365{
ac4d0be5 366 stream_put3(msdp->work_obuf, 0 /* reserved */);
367 stream_putc(msdp->work_obuf, 32 /* sprefix len */);
368 stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr);
369 stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr);
3c72d654 370}
371
ac4d0be5 372static void pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp)
3c72d654 373{
ac4d0be5 374 struct listnode *sanode;
375 struct pim_msdp_sa *sa;
376 int sa_count;
377 int local_cnt = msdp->local_cnt;
378
379 sa_count = 0;
380 if (PIM_DEBUG_MSDP_INTERNAL) {
381 zlog_debug(" sa gen %d", local_cnt);
382 }
383
384 local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt);
385
386 for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
387 if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) {
388 /* current implementation of MSDP is for anycast i.e.
389 * full mesh. so
390 * no re-forwarding of SAs that we learnt from other
391 * peers */
392 continue;
393 }
394 /* add sa into scratch pad */
395 pim_msdp_pkt_sa_fill_one(sa);
396 ++sa_count;
397 if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) {
398 pim_msdp_pkt_sa_push(mp);
399 /* reset headers */
400 sa_count = 0;
401 if (PIM_DEBUG_MSDP_INTERNAL) {
402 zlog_debug(" sa gen for remainder %d",
403 local_cnt);
404 }
405 local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt);
406 }
407 }
408
409 if (sa_count) {
410 pim_msdp_pkt_sa_push(mp);
411 }
412 return;
3c72d654 413}
414
ac4d0be5 415static void pim_msdp_pkt_sa_tx_done(void)
3c72d654 416{
ac4d0be5 417 struct listnode *mpnode;
418 struct pim_msdp_peer *mp;
419
420 /* if SA were sent to the peers we restart ka timer and avoid
421 * unnecessary ka noise */
422 for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
423 if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) {
424 mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT;
425 pim_msdp_peer_pkt_txed(mp);
426 }
427 }
3c72d654 428}
429
ac4d0be5 430void pim_msdp_pkt_sa_tx(void)
3c72d654 431{
ac4d0be5 432 pim_msdp_pkt_sa_gen(NULL /* mp */);
433 pim_msdp_pkt_sa_tx_done();
3c72d654 434}
435
ac4d0be5 436void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa)
3c72d654 437{
ac4d0be5 438 pim_msdp_pkt_sa_fill_hdr(1 /* cnt */);
439 pim_msdp_pkt_sa_fill_one(sa);
440 pim_msdp_pkt_sa_push(NULL);
441 pim_msdp_pkt_sa_tx_done();
3c72d654 442}
443
444/* when a connection is first established we push all SAs immediately */
ac4d0be5 445void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp)
3c72d654 446{
ac4d0be5 447 pim_msdp_pkt_sa_gen(mp);
448 pim_msdp_pkt_sa_tx_done();
3c72d654 449}
450
ac4d0be5 451static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp)
2a333e0f 452{
ac4d0be5 453 pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx");
2a333e0f 454}
455
ac4d0be5 456static void pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len)
2a333e0f 457{
ac4d0be5 458 mp->ka_rx_cnt++;
459 if (len != PIM_MSDP_KA_TLV_MAX_SIZE) {
460 pim_msdp_pkt_rxed_with_fatal_error(mp);
461 return;
462 }
463 pim_msdp_peer_pkt_rxed(mp);
2a333e0f 464}
465
ac4d0be5 466static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp)
3c72d654 467{
ac4d0be5 468 int prefix_len;
469 struct prefix_sg sg;
470
471 /* just throw away the three reserved bytes */
472 stream_get3(mp->ibuf);
473 prefix_len = stream_getc(mp->ibuf);
474
475 memset(&sg, 0, sizeof(struct prefix_sg));
476 sg.grp.s_addr = stream_get_ipv4(mp->ibuf);
477 sg.src.s_addr = stream_get_ipv4(mp->ibuf);
478
479 if (prefix_len != 32) {
480 /* ignore SA update if the prefix length is not 32 */
481 zlog_err("rxed sa update with invalid prefix length %d",
482 prefix_len);
483 return;
484 }
485 if (PIM_DEBUG_MSDP_PACKETS) {
486 zlog_debug(" sg %s", pim_str_sg_dump(&sg));
487 }
488 pim_msdp_sa_ref(mp, &sg, rp);
3c72d654 489}
490
ac4d0be5 491static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len)
2a333e0f 492{
ac4d0be5 493 int entry_cnt;
494 int i;
495 struct in_addr rp; /* Last RP address associated with this SA */
496
497 mp->sa_rx_cnt++;
498
499 if (len < PIM_MSDP_SA_TLV_MIN_SIZE) {
500 pim_msdp_pkt_rxed_with_fatal_error(mp);
501 return;
502 }
503
504 entry_cnt = stream_getc(mp->ibuf);
505 /* some vendors include the actual multicast data in the tlv (at the
506 * end).
507 * we will ignore such data. in the future we may consider pushing it
508 * down
509 * the RPT */
510 if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) {
511 pim_msdp_pkt_rxed_with_fatal_error(mp);
512 return;
513 }
514 rp.s_addr = stream_get_ipv4(mp->ibuf);
515
516 if (PIM_DEBUG_MSDP_PACKETS) {
517 char rp_str[INET_ADDRSTRLEN];
518 pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str));
519 zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str);
520 }
521
522 if (!pim_msdp_peer_rpf_check(mp, rp)) {
523 /* if peer-RPF check fails don't process the packet any further
524 */
525 if (PIM_DEBUG_MSDP_PACKETS) {
526 zlog_debug(" peer RPF check failed");
527 }
528 return;
529 }
530
531 pim_msdp_peer_pkt_rxed(mp);
532
533 /* update SA cache */
534 for (i = 0; i < entry_cnt; ++i) {
535 pim_msdp_pkt_sa_rx_one(mp, rp);
536 }
2a333e0f 537}
538
ac4d0be5 539static void pim_msdp_pkt_rx(struct pim_msdp_peer *mp)
2a333e0f 540{
ac4d0be5 541 enum pim_msdp_tlv type;
542 int len;
543
544 /* re-read type and len */
545 type = stream_getc_from(mp->ibuf, 0);
546 len = stream_getw_from(mp->ibuf, 1);
547 if (len < PIM_MSDP_HEADER_SIZE) {
548 pim_msdp_pkt_rxed_with_fatal_error(mp);
549 return;
550 }
551
552 if (len > PIM_MSDP_SA_TLV_MAX_SIZE) {
553 /* if tlv size if greater than max just ignore the tlv */
554 return;
555 }
556
557 if (PIM_DEBUG_MSDP_PACKETS) {
558 pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/);
559 }
560
561 switch (type) {
562 case PIM_MSDP_KEEPALIVE:
563 pim_msdp_pkt_ka_rx(mp, len);
564 break;
565 case PIM_MSDP_V4_SOURCE_ACTIVE:
566 mp->sa_rx_cnt++;
567 pim_msdp_pkt_sa_rx(mp, len);
568 break;
569 default:
570 mp->unk_rx_cnt++;
571 }
2a333e0f 572}
573
574/* pim msdp read utility function. */
ac4d0be5 575static int pim_msdp_read_packet(struct pim_msdp_peer *mp)
2a333e0f 576{
ac4d0be5 577 int nbytes;
578 int readsize;
579 int old_endp;
580 int new_endp;
581
582 old_endp = stream_get_endp(mp->ibuf);
583 readsize = mp->packet_size - old_endp;
584 if (!readsize) {
585 return 0;
586 }
587
588 /* Read packet from fd */
589 nbytes = stream_read_try(mp->ibuf, mp->fd, readsize);
590 new_endp = stream_get_endp(mp->ibuf);
591 if (nbytes < 0) {
592 if (PIM_DEBUG_MSDP_INTERNAL) {
593 zlog_debug("MSDP peer %s read failed %d", mp->key_str,
594 nbytes);
595 }
596 if (nbytes == -2) {
597 if (PIM_DEBUG_MSDP_INTERNAL) {
598 zlog_debug(
599 "MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d",
600 mp->key_str, old_endp, new_endp);
601 }
602 /* transient error retry */
603 return -1;
604 }
605 pim_msdp_pkt_rxed_with_fatal_error(mp);
606 return -1;
607 }
608
609 if (!nbytes) {
610 if (PIM_DEBUG_MSDP_INTERNAL) {
611 zlog_debug("MSDP peer %s read failed %d", mp->key_str,
612 nbytes);
613 }
614 pim_msdp_peer_reset_tcp_conn(mp, "peer-down");
615 return -1;
616 }
617
618 /* We read partial packet. */
619 if (stream_get_endp(mp->ibuf) != mp->packet_size) {
620 if (PIM_DEBUG_MSDP_INTERNAL) {
621 zlog_debug(
622 "MSDP peer %s read partial len %d old_endp %d new_endp %d",
623 mp->key_str, mp->packet_size, old_endp,
624 new_endp);
625 }
626 return -1;
627 }
628
629 return 0;
2a333e0f 630}
631
ac4d0be5 632int pim_msdp_read(struct thread *thread)
2a333e0f 633{
ac4d0be5 634 struct pim_msdp_peer *mp;
635 int rc;
636 uint32_t len;
637
638 mp = THREAD_ARG(thread);
639 mp->t_read = NULL;
640
641 if (PIM_DEBUG_MSDP_INTERNAL) {
642 zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str);
643 }
644
645 if (mp->fd < 0) {
646 return -1;
647 }
648
649 /* check if TCP connection is established */
650 if (mp->state != PIM_MSDP_ESTABLISHED) {
651 pim_msdp_connect_check(mp);
652 return 0;
653 }
654
655 PIM_MSDP_PEER_READ_ON(mp);
656
657 if (!mp->packet_size) {
658 mp->packet_size = PIM_MSDP_HEADER_SIZE;
659 }
660
661 if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) {
662 /* start by reading the TLV header */
663 rc = pim_msdp_read_packet(mp);
664 if (rc < 0) {
665 goto pim_msdp_read_end;
666 }
667
668 /* Find TLV type and len */
669 stream_getc(mp->ibuf);
670 len = stream_getw(mp->ibuf);
671 if (len < PIM_MSDP_HEADER_SIZE) {
672 pim_msdp_pkt_rxed_with_fatal_error(mp);
673 goto pim_msdp_read_end;
674 }
675 /* read complete TLV */
676 mp->packet_size = len;
677 }
678
679 rc = pim_msdp_read_packet(mp);
680 if (rc < 0) {
681 goto pim_msdp_read_end;
682 }
683
684 pim_msdp_pkt_rx(mp);
685
686 /* reset input buffers and get ready for the next packet */
687 mp->packet_size = 0;
688 stream_reset(mp->ibuf);
3c72d654 689
690pim_msdp_read_end:
ac4d0be5 691 return 0;
2a333e0f 692}