📄 ospf6_message.c
字号:
o6n = (struct ospf6_neighbor *) getdata (n); if (o6n->state < NBS_INIT) continue; if (router_size + sizeof (o6n->router_id) > sizeof (router_buffer)) { zlog_warn ("Send HELLO: Buffer shortage on %s", o6i->interface->name); break; } /* Copy Router-ID to Buffer */ memcpy (router_buffer + router_size, &o6n->router_id, sizeof (o6n->router_id)); router_size += sizeof (o6n->router_id); } OSPF6_MESSAGE_ATTACH (message, router_buffer, router_size); /* set destionation */ inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); /* send hello */ ospf6_message_send (OSPF6_MESSAGE_TYPE_HELLO, message, &dst, o6i->interface->ifindex); /* set next timer thread */ o6i->thread_send_hello = thread_add_timer (master, ospf6_send_hello, o6i, o6i->hello_interval); return 0;}voidospf6_dbdesc_seqnum_init (struct ospf6_neighbor *o6n){ struct timeval tv; if (gettimeofday (&tv, (struct timezone *) NULL) < 0) tv.tv_sec = 1; o6n->dbdesc_seqnum = tv.tv_sec; if (IS_OSPF6_DUMP_DBDESC) zlog_info ("set dbdesc seqnum %d for %s", o6n->dbdesc_seqnum, o6n->str);}intospf6_send_dbdesc_rxmt (struct thread *thread){ struct ospf6_lsdb_node node; struct ospf6_neighbor *o6n; struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_lsa *lsa; struct ospf6_lsa_header *lsa_header; struct ospf6_dbdesc dbdesc; o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); assert (o6n); /* clear thread */ o6n->thread_rxmt_dbdesc = (struct thread *) NULL; /* if state less than ExStart, do nothing */ if (o6n->state < NBS_EXSTART) return 0; OSPF6_MESSAGE_CLEAR (message); /* set dbdesc */ memcpy (dbdesc.options, o6n->ospf6_interface->area->options, sizeof (dbdesc.options)); dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu); dbdesc.bits = o6n->dbdesc_bits; dbdesc.seqnum = htonl (o6n->dbdesc_seqnum); OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc)); /* if this is not initial, set LSA summary to dbdesc */ if (! DD_IS_IBIT_SET (o6n->dbdesc_bits)) { for (ospf6_lsdb_head (&node, o6n->dbdesc_list); ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) { lsa = node.lsa; /* xxx, no MTU check: no support for Dynamic MTU change */ /* set age and add InfTransDelay */ ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); /* set LSA summary to send buffer */ lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr; OSPF6_MESSAGE_ATTACH (message, lsa_header, sizeof (struct ospf6_lsa_header)); } } /* send dbdesc */ ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr, o6n->ospf6_interface->interface->ifindex); /* if master, set futher retransmission */ if (DD_IS_MSBIT_SET (o6n->dbdesc_bits)) o6n->thread_rxmt_dbdesc = thread_add_timer (master, ospf6_send_dbdesc_rxmt, o6n, o6n->ospf6_interface->rxmt_interval); /* statistics */ o6n->ospf6_stat_retrans_dbdesc++; return 0;}intospf6_send_dbdesc (struct thread *thread){ struct ospf6_neighbor *o6n; struct ospf6_lsa *lsa; struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_dbdesc dbdesc; struct ospf6_lsdb_node node; o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); assert (o6n); /* clear thread */ o6n->thread_send_dbdesc = (struct thread *) NULL; if (o6n->thread_rxmt_dbdesc) thread_cancel (o6n->thread_rxmt_dbdesc); o6n->thread_rxmt_dbdesc = (struct thread *) NULL; /* if state less than ExStart, do nothing */ if (o6n->state < NBS_EXSTART) return 0; OSPF6_MESSAGE_CLEAR (message); OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc)); /* clear previous LSA summary sent */ ospf6_lsdb_remove_all (o6n->dbdesc_list); assert (o6n->dbdesc_list->count == 0); /* if this is not initial, set LSA summary to dbdesc */ if (! DD_IS_IBIT_SET (o6n->dbdesc_bits)) { for (ospf6_lsdb_head (&node, o6n->summary_list); ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) { lsa = node.lsa; /* MTU check */ if (OSPF6_MESSAGE_LENGTH (message) + sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_header) > o6n->ospf6_interface->ifmtu) break; /* debug */ if (IS_OSPF6_DUMP_DBDESC) zlog_info ("Include DbDesc: %s", lsa->str); /* attach to dbdesclist */ ospf6_neighbor_dbdesc_add (lsa, o6n); /* detach from summarylist */ ospf6_neighbor_summary_remove (lsa, o6n); /* set age and add InfTransDelay */ ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); /* set LSA summary to send buffer */ OSPF6_MESSAGE_ATTACH (message, lsa->header, sizeof (struct ospf6_lsa_header)); } if (o6n->summary_list->count == 0) { /* Clear more bit */ DD_MBIT_CLEAR (o6n->dbdesc_bits); /* slave must schedule ExchangeDone on sending, here */ if (! DD_IS_MSBIT_SET (o6n->dbdesc_bits)) { if (! DD_IS_MBIT_SET (o6n->dbdesc_bits) && ! DD_IS_MBIT_SET (o6n->last_dd.bits)) thread_add_event (master, exchange_done, o6n, 0); } } } /* if this is initial, set seqnum */ if (DDBIT_IS_INITIAL (o6n->dbdesc_bits)) ospf6_dbdesc_seqnum_init (o6n); /* set dbdesc */ memcpy (dbdesc.options, o6n->ospf6_interface->area->options, sizeof (dbdesc.options)); dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu); dbdesc.bits = o6n->dbdesc_bits; dbdesc.seqnum = htonl (o6n->dbdesc_seqnum); /* send dbdesc */ ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr, o6n->ospf6_interface->interface->ifindex); /* if master, set retransmission */ if (DD_IS_MSBIT_SET (o6n->dbdesc_bits)) o6n->thread_rxmt_dbdesc = thread_add_timer (master, ospf6_send_dbdesc_rxmt, o6n, o6n->ospf6_interface->rxmt_interval); /* statistics */ o6n->lsa_send[OSPF6_MESSAGE_TYPE_DBDESC] += o6n->dbdesc_list->count; return 0;}intospf6_send_lsreq_rxmt (struct thread *thread){ struct ospf6_neighbor *o6n; o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); assert (o6n); o6n->thread_rxmt_lsreq = (struct thread *) NULL; o6n->thread_send_lsreq = thread_add_event (master, ospf6_send_lsreq, o6n, 0); return 0;}intospf6_send_lsreq (struct thread *thread){ struct ospf6_neighbor *o6n; struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_lsreq lsreq[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_lsa *lsa; struct ospf6_lsdb_node node; int i; o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); assert (o6n); /* LSReq will be send only in ExStart or Loading */ if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING) return 0; /* clear thread */ o6n->thread_send_lsreq = (struct thread *) NULL; if (o6n->thread_rxmt_lsreq) thread_cancel (o6n->thread_rxmt_lsreq); o6n->thread_rxmt_lsreq = (struct thread *) NULL; /* schedule loading_done if request list is empty */ if (o6n->request_list->count == 0) { thread_add_event (master, loading_done, o6n, 0); return 0; } /* clear message buffer */ OSPF6_MESSAGE_CLEAR (message); i = 0; for (ospf6_lsdb_head (&node, o6n->request_list); ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) { lsa = node.lsa; /* Buffer Overflow */ if (i >= OSPF6_MESSAGE_IOVEC_SIZE) break; /* I/F MTU check */ if (OSPF6_MESSAGE_LENGTH (message) + sizeof (struct ospf6_lsreq) + sizeof (struct ospf6_header) > o6n->ospf6_interface->ifmtu) break; lsreq[i].mbz = 0; lsreq[i].type = lsa->header->type; lsreq[i].id = lsa->header->id; lsreq[i].adv_router = lsa->header->adv_router; OSPF6_MESSAGE_ATTACH (message, &lsreq[i], sizeof (struct ospf6_lsreq)); i++; } ospf6_message_send (OSPF6_MESSAGE_TYPE_LSREQ, message, &o6n->hisaddr, o6n->ospf6_interface->interface->ifindex); /* set retransmit thread */ o6n->thread_rxmt_lsreq = thread_add_timer (master, ospf6_send_lsreq_rxmt, o6n, o6n->ospf6_interface->rxmt_interval); /* statistics */ o6n->lsa_send[OSPF6_MESSAGE_TYPE_LSREQ] += i; return 0;}/* Send LSUpdate directly to the neighbor, from his retransmission list */intospf6_send_lsupdate_rxmt (struct thread *thread){ struct ospf6_neighbor *o6n; struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_lsupdate lsupdate; struct ospf6_lsa *lsa; struct ospf6_lsdb_node node; o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); assert (o6n); o6n->send_update = (struct thread *) NULL; if (o6n->ospf6_interface->state <= IFS_WAITING) return -1; /* clear message buffer */ OSPF6_MESSAGE_CLEAR (message); /* set lsupdate header */ lsupdate.lsupdate_num = 0; /* set gradually */ OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); /* for each LSA listed on retransmission-list */ for (ospf6_lsdb_head (&node, o6n->retrans_list); ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) { lsa = node.lsa; /* I/F MTU check */ if (OSPF6_MESSAGE_LENGTH (message) + sizeof (struct ospf6_lsupdate) + sizeof (struct ospf6_header) + ntohs (lsa->header->length) > o6n->ospf6_interface->ifmtu) break; ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); OSPF6_MESSAGE_ATTACH (message, lsa->header, ntohs (lsa->header->length)); lsupdate.lsupdate_num++; } /* check and correct lsupdate */ if (lsupdate.lsupdate_num == 0) return 0; lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num); if (IS_OSPF6_DUMP_LSUPDATE) zlog_info ("MESSAGE: retrsnsmit LSUpdate to %s", o6n->str); /* statistics */ o6n->ospf6_stat_retrans_lsupdate++; ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &o6n->hisaddr, o6n->ospf6_interface->if_id); o6n->send_update = thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n, o6n->ospf6_interface->rxmt_interval); return 0;}/* Send LSUpdate containing one LSA directly to the neighbor. This is "implied acknowledgement" */voidospf6_send_lsupdate_direct (struct ospf6_lsa *lsa, struct ospf6_neighbor *o6n){ struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_lsupdate lsupdate; int lsa_len; /* clear message buffer */ OSPF6_MESSAGE_CLEAR (message); /* set lsupdate header */ lsupdate.lsupdate_num = ntohl (1); OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); /* set one LSA */ lsa_len = ntohs (lsa->lsa_hdr->lsh_len); ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len); ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &o6n->hisaddr, o6n->ospf6_interface->if_id);}/* Send LSUpdate containing one LSA by multicast. On non-broadcast link, send it to each neighbor by unicast. This is ordinary flooding */voidospf6_send_lsupdate_flood (struct ospf6_lsa *lsa, struct ospf6_interface *o6i){ struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_lsupdate lsupdate; struct in6_addr dst; int lsa_len; /* clear message buffer */ OSPF6_MESSAGE_CLEAR (message); /* set lsupdate header */ lsupdate.lsupdate_num = ntohl (1); OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); /* set one LSA */ lsa_len = ntohs (lsa->lsa_hdr->lsh_len); ospf6_lsa_age_update_to_send (lsa, o6i->transdelay); OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len); if (if_is_broadcast (o6i->interface)) { /* set destination */ if (o6i->state == IFS_DR || o6i->state == IFS_BDR) inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); else inet_pton (AF_INET6, ALLDROUTERS6, &dst); } else { /* IPv6 relies on link local multicast */ inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); } ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &dst, o6i->if_id);}intospf6_send_lsack_delayed (struct thread *thread){ struct ospf6_interface *o6i; struct iovec message[MAXIOVLIST]; struct ospf6_lsa *lsa; struct ospf6_lsdb_node node; o6i = THREAD_ARG (thread); assert (o6i); if (IS_OSPF6_DUMP_LSACK) zlog_info ("LSACK: Delayed LSAck for %s\n", o6i->interface->name); o6i->thread_send_lsack_delayed = (struct thread *) NULL; if (o6i->state <= IFS_WAITING) return 0; if (o6i->ack_list->count == 0) return 0; iov_clear (message, MAXIOVLIST); for (ospf6_lsdb_head (&node, o6i->ack_list); ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) { lsa = node.lsa; if (IS_OVER_MTU (message, o6i->ifmtu, sizeof (struct ospf6_lsa_hdr))) break; OSPF6_MESSAGE_ATTACH (message, lsa->header, sizeof (struct ospf6_lsa_header)); ospf6_interface_delayed_ack_remove (lsa, o6i); } /* statistics */ o6i->ospf6_stat_delayed_lsack++; switch (o6i->state) { case IFS_DR: case IFS_BDR: ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message, &allspfrouters6.sin6_addr, o6i->if_id); break; default: ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message, &alldrouters6.sin6_addr, o6i->if_id); break; } iov_clear (message, MAXIOVLIST); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -