mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +00:00
Merge pull request #224 from donaldsharp/pim_patches_feb
Pim patches feb
This commit is contained in:
commit
54b19ceaf9
@ -379,9 +379,7 @@ int pim_assert_build_msg(uint8_t *pim_msg, int buf_size,
|
||||
|
||||
/* Encode group */
|
||||
remain = buf_pastend - pim_msg_curr;
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr,
|
||||
remain,
|
||||
group_addr);
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr);
|
||||
if (!pim_msg_curr) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
|
||||
@ -392,9 +390,7 @@ int pim_assert_build_msg(uint8_t *pim_msg, int buf_size,
|
||||
|
||||
/* Encode source */
|
||||
remain = buf_pastend - pim_msg_curr;
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr,
|
||||
remain,
|
||||
source_addr);
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr);
|
||||
if (!pim_msg_curr) {
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "vrf.h"
|
||||
#include "linklist.h"
|
||||
#include "plist.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_iface.h"
|
||||
@ -86,6 +87,9 @@ static void *if_list_clean(struct pim_interface *pim_ifp)
|
||||
list_delete(pim_ifp->pim_ifchannel_list);
|
||||
}
|
||||
|
||||
if (pim_ifp->pim_ifchannel_hash)
|
||||
hash_free (pim_ifp->pim_ifchannel_hash);
|
||||
|
||||
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
|
||||
|
||||
return 0;
|
||||
@ -131,6 +135,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
|
||||
pim_ifp->igmp_socket_list = NULL;
|
||||
pim_ifp->pim_neighbor_list = NULL;
|
||||
pim_ifp->pim_ifchannel_list = NULL;
|
||||
pim_ifp->pim_ifchannel_hash = NULL;
|
||||
pim_ifp->pim_generation_id = 0;
|
||||
|
||||
/* list of struct igmp_sock */
|
||||
@ -161,6 +166,9 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
|
||||
pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free;
|
||||
pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare;
|
||||
|
||||
pim_ifp->pim_ifchannel_hash = hash_create (pim_ifchannel_hash_key,
|
||||
pim_ifchannel_equal);
|
||||
|
||||
ifp->info = pim_ifp;
|
||||
|
||||
pim_sock_reset(ifp);
|
||||
@ -197,6 +205,8 @@ void pim_if_delete(struct interface *ifp)
|
||||
list_delete(pim_ifp->pim_neighbor_list);
|
||||
list_delete(pim_ifp->pim_ifchannel_list);
|
||||
|
||||
hash_free (pim_ifp->pim_ifchannel_hash);
|
||||
|
||||
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
|
||||
|
||||
ifp->info = NULL;
|
||||
|
@ -98,6 +98,7 @@ struct pim_interface {
|
||||
uint16_t pim_override_interval_msec; /* config */
|
||||
struct list *pim_neighbor_list; /* list of struct pim_neighbor */
|
||||
struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */
|
||||
struct hash *pim_ifchannel_hash;
|
||||
|
||||
/* neighbors without lan_delay */
|
||||
int pim_number_of_nonlandelay_neighbors;
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "memory.h"
|
||||
#include "if.h"
|
||||
#include "vrf.h"
|
||||
#include "hash.h"
|
||||
#include "jhash.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_str.h"
|
||||
@ -193,6 +195,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
||||
called by list_delete_all_node()
|
||||
*/
|
||||
listnode_delete(pim_ifp->pim_ifchannel_list, ch);
|
||||
hash_release(pim_ifp->pim_ifchannel_hash, ch);
|
||||
listnode_delete(pim_ifchannel_list, ch);
|
||||
|
||||
pim_ifchannel_free(ch);
|
||||
@ -373,10 +376,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
|
||||
struct prefix_sg *sg)
|
||||
{
|
||||
struct pim_interface *pim_ifp;
|
||||
struct listnode *ch_node;
|
||||
struct pim_ifchannel *ch;
|
||||
|
||||
zassert(ifp);
|
||||
struct pim_ifchannel lookup;
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
|
||||
@ -385,19 +386,13 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
|
||||
__PRETTY_FUNCTION__,
|
||||
pim_str_sg_dump (sg),
|
||||
ifp->name);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
|
||||
if (
|
||||
(sg->src.s_addr == ch->sg.src.s_addr) &&
|
||||
(sg->grp.s_addr == ch->sg.grp.s_addr)
|
||||
) {
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
lookup.sg = *sg;
|
||||
ch = hash_lookup (pim_ifp->pim_ifchannel_hash, &lookup);
|
||||
|
||||
return 0;
|
||||
return ch;
|
||||
}
|
||||
|
||||
static void ifmembership_set(struct pim_ifchannel *ch,
|
||||
@ -553,6 +548,7 @@ pim_ifchannel_add(struct interface *ifp,
|
||||
|
||||
/* Attach to list */
|
||||
listnode_add_sort(pim_ifp->pim_ifchannel_list, ch);
|
||||
ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
|
||||
listnode_add_sort(pim_ifchannel_list, ch);
|
||||
|
||||
return ch;
|
||||
@ -601,8 +597,13 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
|
||||
/* from here ch may have been deleted */
|
||||
|
||||
if (send_prune_echo)
|
||||
pim_joinprune_send (ifp, pim_ifp->primary_address,
|
||||
ch->upstream, 0);
|
||||
{
|
||||
struct pim_rpf rpf;
|
||||
|
||||
rpf.source_nexthop.interface = ifp;
|
||||
rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address;
|
||||
pim_joinprune_send (&rpf, ch->upstream, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -665,28 +666,26 @@ static void check_recv_upstream(int is_join,
|
||||
if (source_flags & PIM_RPT_BIT_MASK) {
|
||||
if (source_flags & PIM_WILDCARD_BIT_MASK) {
|
||||
/* Prune(*,G) to RPF'(S,G) */
|
||||
pim_upstream_join_timer_decrease_to_t_override("Prune(*,G)",
|
||||
up, up->rpf.rpf_addr.u.prefix4);
|
||||
pim_upstream_join_timer_decrease_to_t_override("Prune(*,G)", up);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prune(S,G,rpt) to RPF'(S,G) */
|
||||
pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)",
|
||||
up, up->rpf.rpf_addr.u.prefix4);
|
||||
pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", up);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prune(S,G) to RPF'(S,G) */
|
||||
pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up,
|
||||
up->rpf.rpf_addr.u.prefix4);
|
||||
pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up);
|
||||
}
|
||||
|
||||
static int nonlocal_upstream(int is_join,
|
||||
struct interface *recv_ifp,
|
||||
struct in_addr upstream,
|
||||
struct prefix_sg *sg,
|
||||
uint8_t source_flags,
|
||||
uint16_t holdtime)
|
||||
static int
|
||||
nonlocal_upstream(int is_join,
|
||||
struct interface *recv_ifp,
|
||||
struct in_addr upstream,
|
||||
struct prefix_sg *sg,
|
||||
uint8_t source_flags,
|
||||
uint16_t holdtime)
|
||||
{
|
||||
struct pim_interface *recv_pim_ifp;
|
||||
int is_local; /* boolean */
|
||||
@ -695,27 +694,26 @@ static int nonlocal_upstream(int is_join,
|
||||
zassert(recv_pim_ifp);
|
||||
|
||||
is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr);
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE_DETAIL) {
|
||||
char up_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
|
||||
zlog_warn("%s: recv %s (S,G)=%s to %s upstream=%s on %s",
|
||||
__PRETTY_FUNCTION__,
|
||||
is_join ? "join" : "prune",
|
||||
pim_str_sg_dump (sg),
|
||||
is_local ? "local" : "non-local",
|
||||
up_str, recv_ifp->name);
|
||||
}
|
||||
|
||||
if (is_local)
|
||||
return 0;
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE_DETAIL) {
|
||||
char up_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
|
||||
zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s",
|
||||
__PRETTY_FUNCTION__,
|
||||
is_join ? "join" : "prune",
|
||||
pim_str_sg_dump (sg),
|
||||
up_str, recv_ifp->name);
|
||||
}
|
||||
|
||||
/*
|
||||
Since recv upstream addr was not directed to our primary
|
||||
address, check if we should react to it in any way.
|
||||
*/
|
||||
* Since recv upstream addr was not directed to our primary
|
||||
* address, check if we should react to it in any way.
|
||||
*/
|
||||
check_recv_upstream(is_join, recv_ifp, upstream, sg,
|
||||
source_flags, holdtime);
|
||||
source_flags, holdtime);
|
||||
|
||||
return 1; /* non-local */
|
||||
}
|
||||
@ -972,7 +970,7 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
__FILE__, __PRETTY_FUNCTION__,
|
||||
child->sg_str, ifp->name, up->sg_str);
|
||||
|
||||
if (pim_upstream_evaluate_join_desired (child))
|
||||
if (pim_upstream_evaluate_join_desired_interface (child, ch))
|
||||
{
|
||||
pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||
pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
|
||||
@ -1019,7 +1017,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
||||
__FILE__, __PRETTY_FUNCTION__,
|
||||
up->sg_str, ifp->name, child->sg_str);
|
||||
|
||||
if (c_oil && !pim_upstream_evaluate_join_desired (child))
|
||||
if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch))
|
||||
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||
|
||||
/*
|
||||
@ -1231,3 +1229,24 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
pim_ifchannel_hash_key (void *arg)
|
||||
{
|
||||
struct pim_ifchannel *ch = (struct pim_ifchannel *)arg;
|
||||
|
||||
return jhash_2words (ch->sg.src.s_addr, ch->sg.grp.s_addr, 0);
|
||||
}
|
||||
|
||||
int
|
||||
pim_ifchannel_equal (const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1;
|
||||
const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2;
|
||||
|
||||
if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) &&
|
||||
(ch1->sg.src.s_addr == ch2->sg.src.s_addr))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "if.h"
|
||||
#include "prefix.h"
|
||||
|
||||
struct pim_ifchannel;
|
||||
#include "pim_upstream.h"
|
||||
|
||||
enum pim_ifmembership {
|
||||
@ -153,4 +154,7 @@ void pim_ifchannel_scan_forward_start (struct interface *new_ifp);
|
||||
void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom);
|
||||
|
||||
int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2);
|
||||
|
||||
unsigned int pim_ifchannel_hash_key (void *arg);
|
||||
int pim_ifchannel_equal (const void *arg1, const void *arg2);
|
||||
#endif /* PIM_IFCHANNEL_H */
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "memory.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "hash.h"
|
||||
#include "jhash.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_igmp.h"
|
||||
@ -428,23 +430,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
|
||||
from_str, to_str, igmp->interface->name, len, ip_hlen, ip_hdr->ip_p);
|
||||
}
|
||||
|
||||
if (ip_hdr->ip_p != PIM_IP_PROTO_IGMP) {
|
||||
zlog_warn("IP packet protocol=%d is not IGMP=%d",
|
||||
ip_hdr->ip_p, PIM_IP_PROTO_IGMP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip_hlen < PIM_IP_HEADER_MIN_LEN) {
|
||||
zlog_warn("IP packet header size=%zu shorter than minimum=%d",
|
||||
ip_hlen, PIM_IP_HEADER_MIN_LEN);
|
||||
return -1;
|
||||
}
|
||||
if (ip_hlen > PIM_IP_HEADER_MAX_LEN) {
|
||||
zlog_warn("IP packet header size=%zu greater than maximum=%d",
|
||||
ip_hlen, PIM_IP_HEADER_MAX_LEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
igmp_msg = buf + ip_hlen;
|
||||
msg_type = *igmp_msg;
|
||||
igmp_msg_len = len - ip_hlen;
|
||||
@ -730,6 +715,8 @@ static void igmp_group_delete(struct igmp_group *group)
|
||||
|
||||
group_timer_off(group);
|
||||
listnode_delete(group->group_igmp_sock->igmp_group_list, group);
|
||||
hash_release (group->group_igmp_sock->igmp_group_hash, group);
|
||||
|
||||
igmp_group_free(group);
|
||||
}
|
||||
|
||||
@ -750,6 +737,7 @@ void igmp_sock_free(struct igmp_sock *igmp)
|
||||
zassert(!listcount(igmp->igmp_group_list));
|
||||
|
||||
list_free(igmp->igmp_group_list);
|
||||
hash_free(igmp->igmp_group_hash);
|
||||
|
||||
XFREE(MTYPE_PIM_IGMP_SOCKET, igmp);
|
||||
}
|
||||
@ -790,6 +778,26 @@ igmp_sock_delete_all (struct interface *ifp)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
igmp_group_hash_key (void *arg)
|
||||
{
|
||||
struct igmp_group *group = (struct igmp_group *)arg;
|
||||
|
||||
return jhash_1word(group->group_addr.s_addr, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
igmp_group_hash_equal (const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct igmp_group *g1 = (const struct igmp_group *)arg1;
|
||||
const struct igmp_group *g2 = (const struct igmp_group *)arg2;
|
||||
|
||||
if (g1->group_addr.s_addr == g2->group_addr.s_addr)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct igmp_sock *igmp_sock_new(int fd,
|
||||
struct in_addr ifaddr,
|
||||
struct interface *ifp)
|
||||
@ -819,6 +827,9 @@ static struct igmp_sock *igmp_sock_new(int fd,
|
||||
}
|
||||
igmp->igmp_group_list->del = (void (*)(void *)) igmp_group_free;
|
||||
|
||||
igmp->igmp_group_hash = hash_create (igmp_group_hash_key,
|
||||
igmp_group_hash_equal);
|
||||
|
||||
igmp->fd = fd;
|
||||
igmp->interface = ifp;
|
||||
igmp->ifaddr = ifaddr;
|
||||
@ -1029,14 +1040,11 @@ struct igmp_group *
|
||||
find_group_by_addr (struct igmp_sock *igmp,
|
||||
struct in_addr group_addr)
|
||||
{
|
||||
struct igmp_group *group;
|
||||
struct listnode *node;
|
||||
struct igmp_group lookup;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, node, group))
|
||||
if (group_addr.s_addr == group->group_addr.s_addr)
|
||||
return group;
|
||||
lookup.group_addr.s_addr = group_addr.s_addr;
|
||||
|
||||
return 0;
|
||||
return hash_lookup(igmp->igmp_group_hash, &lookup);
|
||||
}
|
||||
|
||||
struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
|
||||
@ -1105,6 +1113,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
|
||||
group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */
|
||||
|
||||
listnode_add(igmp->igmp_group_list, group);
|
||||
group = hash_get (igmp->igmp_group_hash, group, hash_alloc_intern);
|
||||
|
||||
if (PIM_DEBUG_IGMP_TRACE) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
|
@ -89,6 +89,7 @@ struct igmp_sock {
|
||||
int startup_query_count;
|
||||
|
||||
struct list *igmp_group_list; /* list of struct igmp_group */
|
||||
struct hash *igmp_group_hash;
|
||||
};
|
||||
|
||||
struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,
|
||||
|
@ -303,37 +303,33 @@ int pim_joinprune_recv(struct interface *ifp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pim_joinprune_send(struct interface *ifp,
|
||||
struct in_addr upstream_addr,
|
||||
struct pim_upstream *up,
|
||||
int send_join)
|
||||
int pim_joinprune_send(struct pim_rpf *rpf,
|
||||
struct pim_upstream *up,
|
||||
int send_join)
|
||||
{
|
||||
struct pim_interface *pim_ifp;
|
||||
uint8_t pim_msg[9000];
|
||||
int pim_msg_size;
|
||||
|
||||
on_trace (__PRETTY_FUNCTION__, ifp, upstream_addr);
|
||||
on_trace (__PRETTY_FUNCTION__, rpf->source_nexthop.interface, rpf->rpf_addr.u.prefix4);
|
||||
|
||||
zassert(ifp);
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
pim_ifp = rpf->source_nexthop.interface->info;
|
||||
|
||||
if (!pim_ifp) {
|
||||
zlog_warn("%s: multicast not enabled on interface %s",
|
||||
__PRETTY_FUNCTION__,
|
||||
ifp->name);
|
||||
__PRETTY_FUNCTION__,
|
||||
rpf->source_nexthop.interface->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (PIM_INADDR_IS_ANY(upstream_addr)) {
|
||||
if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) {
|
||||
if (PIM_DEBUG_PIM_J_P) {
|
||||
char dst_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<dst?>", upstream_addr, dst_str, sizeof(dst_str));
|
||||
pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str));
|
||||
zlog_debug("%s: %s(S,G)=%s: upstream=%s is myself on interface %s",
|
||||
__PRETTY_FUNCTION__,
|
||||
send_join ? "Join" : "Prune",
|
||||
up->sg_str, dst_str, ifp->name);
|
||||
up->sg_str, dst_str, rpf->source_nexthop.interface->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -347,24 +343,24 @@ int pim_joinprune_send(struct interface *ifp,
|
||||
relevant Hello message without waiting for the Hello Timer to
|
||||
expire, followed by the Join/Prune or Assert message.
|
||||
*/
|
||||
pim_hello_require(ifp);
|
||||
pim_hello_require(rpf->source_nexthop.interface);
|
||||
|
||||
/*
|
||||
Build PIM message
|
||||
*/
|
||||
pim_msg_size = pim_msg_join_prune_encode (pim_msg, 9000, send_join,
|
||||
up, upstream_addr, PIM_JP_HOLDTIME);
|
||||
up, rpf->rpf_addr.u.prefix4, PIM_JP_HOLDTIME);
|
||||
|
||||
if (pim_msg_size < 0)
|
||||
return pim_msg_size;
|
||||
|
||||
if (PIM_DEBUG_PIM_J_P) {
|
||||
char dst_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<dst?>", upstream_addr, dst_str, sizeof(dst_str));
|
||||
pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str));
|
||||
zlog_debug("%s: sending %s(S,G)=%s to upstream=%s on interface %s",
|
||||
__PRETTY_FUNCTION__,
|
||||
send_join ? "Join" : "Prune",
|
||||
up->sg_str, dst_str, ifp->name);
|
||||
up->sg_str, dst_str, rpf->source_nexthop.interface->name);
|
||||
}
|
||||
|
||||
if (pim_msg_send(pim_ifp->pim_sock_fd,
|
||||
@ -372,9 +368,9 @@ int pim_joinprune_send(struct interface *ifp,
|
||||
qpim_all_pim_routers_addr,
|
||||
pim_msg,
|
||||
pim_msg_size,
|
||||
ifp->name)) {
|
||||
rpf->source_nexthop.interface->name)) {
|
||||
zlog_warn("%s: could not send PIM message on interface %s",
|
||||
__PRETTY_FUNCTION__, ifp->name);
|
||||
__PRETTY_FUNCTION__, rpf->source_nexthop.interface->name);
|
||||
return -8;
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,8 @@ int pim_joinprune_recv(struct interface *ifp,
|
||||
struct in_addr src_addr,
|
||||
uint8_t *tlv_buf, int tlv_buf_size);
|
||||
|
||||
int pim_joinprune_send(struct interface *ifp,
|
||||
struct in_addr upstream_addr,
|
||||
struct pim_upstream *up,
|
||||
int send_join);
|
||||
int pim_joinprune_send(struct pim_rpf *nexthop,
|
||||
struct pim_upstream *up,
|
||||
int send_join);
|
||||
|
||||
#endif /* PIM_JOIN_H */
|
||||
|
@ -351,7 +351,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf)
|
||||
struct pim_interface *pim_ifp;
|
||||
struct pim_ifchannel *ch;
|
||||
struct pim_upstream *up;
|
||||
//struct prefix_sg star_g;
|
||||
struct prefix_sg star_g;
|
||||
struct prefix_sg sg;
|
||||
struct channel_oil *oil;
|
||||
|
||||
@ -367,9 +367,10 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf)
|
||||
ch->sg_str, ifp->name);
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
|
||||
star_g = sg;
|
||||
star_g.src.s_addr = INADDR_ANY;
|
||||
#if 0
|
||||
ch = pim_ifchannel_find(ifp, &star_g);
|
||||
if (ch)
|
||||
{
|
||||
@ -383,11 +384,22 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf)
|
||||
up = pim_upstream_find (&sg);
|
||||
if (up)
|
||||
{
|
||||
struct pim_upstream *parent;
|
||||
struct pim_nexthop source;
|
||||
struct pim_rpf *rpf = RP (sg.grp);
|
||||
if (!rpf || !rpf->source_nexthop.interface)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we have received a WRVIFWHOLE and are at this
|
||||
* point, we could be receiving the packet on the *,G
|
||||
* tree, let's check and if so we can safely drop
|
||||
* it.
|
||||
*/
|
||||
parent = pim_upstream_find (&star_g);
|
||||
if (parent && parent->rpf.source_nexthop.interface == ifp)
|
||||
return 0;
|
||||
|
||||
pim_ifp = rpf->source_nexthop.interface->info;
|
||||
|
||||
memset (&source, 0, sizeof (source));
|
||||
|
349
pimd/pim_msg.c
349
pimd/pim_msg.c
@ -37,163 +37,72 @@
|
||||
#include "pim_rpf.h"
|
||||
#include "pim_register.h"
|
||||
|
||||
void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size,
|
||||
uint8_t pim_msg_type)
|
||||
void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type)
|
||||
{
|
||||
uint16_t checksum;
|
||||
|
||||
zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
|
||||
struct pim_msg_header *header = (struct pim_msg_header *)pim_msg;
|
||||
|
||||
/*
|
||||
* Write header
|
||||
*/
|
||||
header->ver = PIM_PROTO_VERSION;
|
||||
header->type = pim_msg_type;
|
||||
header->reserved = 0;
|
||||
|
||||
*(uint8_t *) PIM_MSG_HDR_OFFSET_VERSION(pim_msg) = (PIM_PROTO_VERSION << 4) | pim_msg_type;
|
||||
*(uint8_t *) PIM_MSG_HDR_OFFSET_RESERVED(pim_msg) = 0;
|
||||
|
||||
/*
|
||||
* Compute checksum
|
||||
*/
|
||||
|
||||
*(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM (pim_msg) = 0;
|
||||
header->checksum = 0;
|
||||
/*
|
||||
* The checksum for Registers is done only on the first 8 bytes of the packet,
|
||||
* including the PIM header and the next 4 bytes, excluding the data packet portion
|
||||
*/
|
||||
if (pim_msg_type == PIM_MSG_TYPE_REGISTER)
|
||||
checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN);
|
||||
header->checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN);
|
||||
else
|
||||
checksum = in_cksum (pim_msg, pim_msg_size);
|
||||
|
||||
*(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = checksum;
|
||||
header->checksum = in_cksum (pim_msg, pim_msg_size);
|
||||
}
|
||||
|
||||
uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf,
|
||||
int buf_size,
|
||||
struct in_addr addr)
|
||||
uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr)
|
||||
{
|
||||
const int ENCODED_IPV4_UCAST_SIZE = 6;
|
||||
|
||||
if (buf_size < ENCODED_IPV4_UCAST_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */
|
||||
buf[1] = '\0'; /* native encoding */
|
||||
memcpy(buf+2, &addr, sizeof(struct in_addr));
|
||||
|
||||
return buf + ENCODED_IPV4_UCAST_SIZE;
|
||||
return buf + PIM_ENCODED_IPV4_UCAST_SIZE;
|
||||
}
|
||||
|
||||
uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf,
|
||||
int buf_size,
|
||||
struct in_addr addr)
|
||||
uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr)
|
||||
{
|
||||
const int ENCODED_IPV4_GROUP_SIZE = 8;
|
||||
|
||||
if (buf_size < ENCODED_IPV4_GROUP_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */
|
||||
buf[1] = '\0'; /* native encoding */
|
||||
buf[2] = '\0'; /* reserved */
|
||||
buf[3] = 32; /* mask len */
|
||||
memcpy(buf+4, &addr, sizeof(struct in_addr));
|
||||
|
||||
return buf + ENCODED_IPV4_GROUP_SIZE;
|
||||
return buf + PIM_ENCODED_IPV4_GROUP_SIZE;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size,
|
||||
struct in_addr addr, uint8_t bits)
|
||||
pim_msg_addr_encode_ipv4_source(uint8_t *buf,
|
||||
struct in_addr addr, uint8_t bits)
|
||||
{
|
||||
const int ENCODED_IPV4_SOURCE_SIZE = 8;
|
||||
|
||||
if (buf_size < ENCODED_IPV4_SOURCE_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */
|
||||
buf[1] = '\0'; /* native encoding */
|
||||
buf[2] = bits;
|
||||
buf[3] = 32; /* mask len */
|
||||
memcpy(buf+4, &addr, sizeof(struct in_addr));
|
||||
|
||||
return buf + ENCODED_IPV4_SOURCE_SIZE;
|
||||
return buf + PIM_ENCODED_IPV4_SOURCE_SIZE;
|
||||
}
|
||||
|
||||
int
|
||||
pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join,
|
||||
struct pim_upstream *up,
|
||||
struct in_addr upstream, int holdtime)
|
||||
static size_t
|
||||
pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_upstream *up, int is_join)
|
||||
{
|
||||
uint8_t *pim_msg = buf;
|
||||
uint8_t *pim_msg_curr = buf + PIM_MSG_HEADER_LEN;
|
||||
uint8_t *end = buf + buf_size;
|
||||
uint16_t *prunes = NULL;
|
||||
uint16_t *joins = NULL;
|
||||
struct in_addr stosend;
|
||||
uint8_t bits;
|
||||
int remain;
|
||||
|
||||
remain = end - pim_msg_curr;
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, buf_size - PIM_MSG_HEADER_LEN, upstream);
|
||||
if (!pim_msg_curr) {
|
||||
char dst_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<dst?>", upstream, dst_str, sizeof(dst_str));
|
||||
zlog_warn("%s: failure encoding destination address %s: space left=%d",
|
||||
__PRETTY_FUNCTION__, dst_str, remain);
|
||||
return -3;
|
||||
}
|
||||
/* number of joined/pruned sources */
|
||||
grp->joins = htons(is_join ? 1 : 0);
|
||||
grp->prunes = htons(is_join ? 0 : 1);
|
||||
|
||||
remain = end - pim_msg_curr;
|
||||
if (remain < 4) {
|
||||
zlog_warn("%s: group will not fit: space left=%d",
|
||||
__PRETTY_FUNCTION__, remain);
|
||||
return -4;
|
||||
}
|
||||
|
||||
*pim_msg_curr = 0; /* reserved */
|
||||
++pim_msg_curr;
|
||||
*pim_msg_curr = 1; /* number of groups */
|
||||
++pim_msg_curr;
|
||||
|
||||
*((uint16_t *) pim_msg_curr) = htons(holdtime);
|
||||
++pim_msg_curr;
|
||||
++pim_msg_curr;
|
||||
|
||||
remain = end - pim_msg_curr;
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_group (pim_msg_curr, remain,
|
||||
up->sg.grp);
|
||||
if (!pim_msg_curr) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<grp?>", up->sg.grp, group_str, sizeof(group_str));
|
||||
zlog_warn("%s: failure encoding group address %s: space left=%d",
|
||||
__PRETTY_FUNCTION__, group_str, remain);
|
||||
return -5;
|
||||
}
|
||||
|
||||
remain = end - pim_msg_curr;
|
||||
if (remain < 4) {
|
||||
zlog_warn("%s: sources will not fit: space left=%d",
|
||||
__PRETTY_FUNCTION__, remain);
|
||||
return -6;
|
||||
}
|
||||
|
||||
/* number of joined sources */
|
||||
joins = (uint16_t *)pim_msg_curr;
|
||||
*joins = htons(is_join ? 1 : 0);
|
||||
++pim_msg_curr;
|
||||
++pim_msg_curr;
|
||||
|
||||
/* number of pruned sources */
|
||||
prunes = (uint16_t *)pim_msg_curr;
|
||||
*prunes = htons(is_join ? 0 : 1);
|
||||
++pim_msg_curr;
|
||||
++pim_msg_curr;
|
||||
|
||||
remain = end - pim_msg_curr;
|
||||
if (up->sg.src.s_addr == INADDR_ANY)
|
||||
{
|
||||
struct pim_rpf *rpf = pim_rp_g (up->sg.grp);
|
||||
@ -205,15 +114,14 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join,
|
||||
bits = PIM_ENCODE_SPARSE_BIT;
|
||||
stosend = up->sg.src;
|
||||
}
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, stosend, bits);
|
||||
if (!pim_msg_curr) {
|
||||
|
||||
if (!pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[0], stosend, bits)) {
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<src?>", up->sg.src, source_str, sizeof(source_str));
|
||||
zlog_warn("%s: failure encoding source address %s: space left=%d",
|
||||
__PRETTY_FUNCTION__, source_str, remain);
|
||||
return -7;
|
||||
zlog_warn("%s: failure encoding source address %s",
|
||||
__PRETTY_FUNCTION__, source_str);
|
||||
return 0;
|
||||
}
|
||||
remain = pim_msg_curr - pim_msg;
|
||||
|
||||
/*
|
||||
* This is not implemented correctly at this point in time
|
||||
@ -227,61 +135,162 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join,
|
||||
int send_prune = 0;
|
||||
|
||||
zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune",
|
||||
__PRETTY_FUNCTION__, up->sg_str);
|
||||
__PRETTY_FUNCTION__, up->sg_str);
|
||||
for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child))
|
||||
{
|
||||
if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
||||
{
|
||||
if (!pim_rpf_is_same(&up->rpf, &child->rpf))
|
||||
{
|
||||
send_prune = 1;
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else if (pim_upstream_is_sg_rpt (child))
|
||||
{
|
||||
if (pim_upstream_empty_inherited_olist (child))
|
||||
{
|
||||
send_prune = 1;
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message",
|
||||
__PRETTY_FUNCTION__, child->sg_str);
|
||||
}
|
||||
else if (!pim_rpf_is_same (&up->rpf, &child->rpf))
|
||||
{
|
||||
send_prune = 1;
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: SPT bit is not set for (%s)",
|
||||
__PRETTY_FUNCTION__, child->sg_str);
|
||||
if (send_prune)
|
||||
{
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain,
|
||||
child->sg.src,
|
||||
PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT);
|
||||
remain = pim_msg_curr - pim_msg;
|
||||
*prunes = htons(ntohs(*prunes) + 1);
|
||||
send_prune = 0;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
||||
{
|
||||
if (!pim_rpf_is_same(&up->rpf, &child->rpf))
|
||||
{
|
||||
send_prune = 1;
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else if (pim_upstream_is_sg_rpt (child))
|
||||
{
|
||||
if (pim_upstream_empty_inherited_olist (child))
|
||||
{
|
||||
send_prune = 1;
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message",
|
||||
__PRETTY_FUNCTION__, child->sg_str);
|
||||
}
|
||||
else if (!pim_rpf_is_same (&up->rpf, &child->rpf))
|
||||
{
|
||||
send_prune = 1;
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message",
|
||||
__PRETTY_FUNCTION__, up->sg_str, child->sg_str);
|
||||
}
|
||||
else
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug ("%s: SPT bit is not set for (%s)",
|
||||
__PRETTY_FUNCTION__, child->sg_str);
|
||||
if (send_prune)
|
||||
{
|
||||
pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain,
|
||||
child->sg.src,
|
||||
PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT);
|
||||
remain = pim_msg_curr - pim_msg;
|
||||
*prunes = htons(ntohs(*prunes) + 1);
|
||||
send_prune = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pim_msg_build_header (pim_msg, remain, PIM_MSG_TYPE_JOIN_PRUNE);
|
||||
|
||||
return remain;
|
||||
return sizeof (*grp);
|
||||
}
|
||||
|
||||
/*
|
||||
* J/P Message Format
|
||||
*
|
||||
* While the RFC clearly states that this is 32 bits wide, it
|
||||
* is cheating. These fields:
|
||||
* Encoded-Unicast format (6 bytes MIN)
|
||||
* Encoded-Group format (8 bytes MIN)
|
||||
* Encoded-Source format (8 bytes MIN)
|
||||
* are *not* 32 bits wide.
|
||||
*
|
||||
* Nor does the RFC explicitly call out the size for:
|
||||
* Reserved (1 byte)
|
||||
* Num Groups (1 byte)
|
||||
* Holdtime (2 bytes)
|
||||
* Number of Joined Sources (2 bytes)
|
||||
* Number of Pruned Sources (2 bytes)
|
||||
*
|
||||
* This leads to a missleading representation from casual
|
||||
* reading and making assumptions. Be careful!
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |PIM Ver| Type | Reserved | Checksum |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Upstream Neighbor Address (Encoded-Unicast format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Reserved | Num groups | Holdtime |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Multicast Group Address 1 (Encoded-Group format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Number of Joined Sources | Number of Pruned Sources |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Joined Source Address 1 (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | . |
|
||||
* | . |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Joined Source Address n (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Pruned Source Address 1 (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | . |
|
||||
* | . |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Pruned Source Address n (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Multicast Group Address m (Encoded-Group format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Number of Joined Sources | Number of Pruned Sources |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Joined Source Address 1 (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | . |
|
||||
* | . |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Joined Source Address n (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Pruned Source Address 1 (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | . |
|
||||
* | . |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Pruned Source Address n (Encoded-Source format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
int
|
||||
pim_msg_join_prune_encode (uint8_t *buf, size_t buf_size, int is_join,
|
||||
struct pim_upstream *up,
|
||||
struct in_addr upstream, int holdtime)
|
||||
{
|
||||
struct pim_jp *msg = (struct pim_jp *)buf;
|
||||
|
||||
assert(buf_size > sizeof (struct pim_jp));
|
||||
|
||||
if (!pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, upstream)) {
|
||||
char dst_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<dst?>", upstream, dst_str, sizeof(dst_str));
|
||||
zlog_warn("%s: failure encoding destination address %s",
|
||||
__PRETTY_FUNCTION__, dst_str);
|
||||
return -3;
|
||||
}
|
||||
|
||||
msg->reserved = 0;
|
||||
msg->num_groups = 1;
|
||||
msg->holdtime = htons(holdtime);
|
||||
|
||||
if (!pim_msg_addr_encode_ipv4_group ((uint8_t *)&msg->groups[0].g, up->sg.grp)) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<grp?>", up->sg.grp, group_str, sizeof(group_str));
|
||||
zlog_warn("%s: failure encoding group address %s",
|
||||
__PRETTY_FUNCTION__, group_str);
|
||||
return -5;
|
||||
}
|
||||
|
||||
pim_msg_build_jp_groups (&msg->groups[0], up, is_join);
|
||||
|
||||
pim_msg_build_header (buf, sizeof (struct pim_jp), PIM_MSG_TYPE_JOIN_PRUNE);
|
||||
|
||||
return sizeof (struct pim_jp);
|
||||
}
|
||||
|
@ -35,25 +35,66 @@
|
||||
*/
|
||||
#define PIM_MSG_ADDRESS_FAMILY_IPV4 (1)
|
||||
|
||||
void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size,
|
||||
uint8_t pim_msg_type);
|
||||
uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf,
|
||||
int buf_size,
|
||||
struct in_addr addr);
|
||||
uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf,
|
||||
int buf_size,
|
||||
struct in_addr addr);
|
||||
/*
|
||||
* Network Order pim_msg_hdr
|
||||
*/
|
||||
struct pim_msg_header {
|
||||
uint8_t type:4;
|
||||
uint8_t ver:4;
|
||||
uint8_t reserved;
|
||||
uint16_t checksum;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct pim_encoded_ipv4_unicast {
|
||||
uint8_t family;
|
||||
uint8_t reserved;
|
||||
struct in_addr addr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct pim_encoded_group_ipv4 {
|
||||
uint8_t ne;
|
||||
uint8_t family;
|
||||
uint8_t reserved;
|
||||
uint8_t mask;
|
||||
struct in_addr addr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct pim_encoded_source_ipv4 {
|
||||
uint8_t ne;
|
||||
uint8_t family;
|
||||
uint8_t bits;
|
||||
uint8_t mask;
|
||||
struct in_addr addr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct pim_jp_groups {
|
||||
struct pim_encoded_group_ipv4 g;
|
||||
uint16_t joins;
|
||||
uint16_t prunes;
|
||||
struct pim_encoded_source_ipv4 s[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct pim_jp {
|
||||
struct pim_msg_header header;
|
||||
struct pim_encoded_ipv4_unicast addr;
|
||||
uint8_t reserved;
|
||||
uint8_t num_groups;
|
||||
uint16_t holdtime;
|
||||
struct pim_jp_groups groups[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type);
|
||||
uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr);
|
||||
uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr);
|
||||
|
||||
#define PIM_ENCODE_SPARSE_BIT 0x04
|
||||
#define PIM_ENCODE_WC_BIT 0x02
|
||||
#define PIM_ENCODE_RPT_BIT 0x01
|
||||
uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf,
|
||||
int buf_size,
|
||||
struct in_addr addr,
|
||||
uint8_t bits);
|
||||
struct in_addr addr, uint8_t bits);
|
||||
|
||||
|
||||
int pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join,
|
||||
struct pim_upstream *up,
|
||||
struct in_addr upstream, int holdtime);
|
||||
int pim_msg_join_prune_encode (uint8_t *buf, size_t buf_size, int is_join,
|
||||
struct pim_upstream *up,
|
||||
struct in_addr upstream, int holdtime);
|
||||
#endif /* PIM_MSG_H */
|
||||
|
@ -133,27 +133,40 @@ void pim_channel_oil_free(struct channel_oil *c_oil)
|
||||
XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil);
|
||||
}
|
||||
|
||||
static void
|
||||
pim_del_channel_oil (struct channel_oil *c_oil)
|
||||
static struct channel_oil *
|
||||
pim_find_channel_oil(struct prefix_sg *sg)
|
||||
{
|
||||
/*
|
||||
notice that listnode_delete() can't be moved
|
||||
into pim_channel_oil_free() because the later is
|
||||
called by list_delete_all_node()
|
||||
*/
|
||||
listnode_delete(pim_channel_oil_list, c_oil);
|
||||
hash_release (pim_channel_oil_hash, c_oil);
|
||||
struct channel_oil *c_oil = NULL;
|
||||
struct channel_oil lookup;
|
||||
|
||||
pim_channel_oil_free(c_oil);
|
||||
lookup.oil.mfcc_mcastgrp = sg->grp;
|
||||
lookup.oil.mfcc_origin = sg->src;
|
||||
|
||||
c_oil = hash_lookup (pim_channel_oil_hash, &lookup);
|
||||
|
||||
return c_oil;
|
||||
}
|
||||
|
||||
static struct channel_oil *
|
||||
pim_add_channel_oil (struct prefix_sg *sg,
|
||||
int input_vif_index)
|
||||
struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
|
||||
int input_vif_index)
|
||||
{
|
||||
struct channel_oil *c_oil;
|
||||
struct interface *ifp;
|
||||
|
||||
c_oil = pim_find_channel_oil(sg);
|
||||
if (c_oil) {
|
||||
if (c_oil->oil.mfcc_parent != input_vif_index)
|
||||
{
|
||||
c_oil->oil_inherited_rescan = 1;
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d",
|
||||
__PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index);
|
||||
}
|
||||
c_oil->oil.mfcc_parent = input_vif_index;
|
||||
++c_oil->oil_ref_count;
|
||||
return c_oil;
|
||||
}
|
||||
|
||||
ifp = pim_if_find_by_vif_index(input_vif_index);
|
||||
if (!ifp) {
|
||||
/* warning only */
|
||||
@ -181,47 +194,20 @@ pim_add_channel_oil (struct prefix_sg *sg,
|
||||
return c_oil;
|
||||
}
|
||||
|
||||
static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg)
|
||||
{
|
||||
struct channel_oil *c_oil = NULL;
|
||||
struct channel_oil lookup;
|
||||
|
||||
lookup.oil.mfcc_mcastgrp = sg->grp;
|
||||
lookup.oil.mfcc_origin = sg->src;
|
||||
|
||||
c_oil = hash_lookup (pim_channel_oil_hash, &lookup);
|
||||
|
||||
return c_oil;
|
||||
}
|
||||
|
||||
struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,
|
||||
int input_vif_index)
|
||||
{
|
||||
struct channel_oil *c_oil;
|
||||
|
||||
c_oil = pim_find_channel_oil(sg);
|
||||
if (c_oil) {
|
||||
if (c_oil->oil.mfcc_parent != input_vif_index)
|
||||
{
|
||||
c_oil->oil_inherited_rescan = 1;
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d",
|
||||
__PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index);
|
||||
}
|
||||
c_oil->oil.mfcc_parent = input_vif_index;
|
||||
++c_oil->oil_ref_count;
|
||||
return c_oil;
|
||||
}
|
||||
|
||||
return pim_add_channel_oil(sg, input_vif_index);
|
||||
}
|
||||
|
||||
void pim_channel_oil_del(struct channel_oil *c_oil)
|
||||
{
|
||||
--c_oil->oil_ref_count;
|
||||
|
||||
if (c_oil->oil_ref_count < 1) {
|
||||
pim_del_channel_oil(c_oil);
|
||||
/*
|
||||
* notice that listnode_delete() can't be moved
|
||||
* into pim_channel_oil_free() because the later is
|
||||
* called by list_delete_all_node()
|
||||
*/
|
||||
listnode_delete(pim_channel_oil_list, c_oil);
|
||||
hash_release (pim_channel_oil_hash, c_oil);
|
||||
|
||||
pim_channel_oil_free(c_oil);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,11 +135,10 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
|
||||
char dst_str[INET_ADDRSTRLEN];
|
||||
uint8_t *pim_msg;
|
||||
int pim_msg_len;
|
||||
uint8_t pim_version;
|
||||
enum pim_msg_type pim_type;
|
||||
uint16_t pim_checksum; /* received checksum */
|
||||
uint16_t checksum; /* computed checksum */
|
||||
struct pim_neighbor *neigh;
|
||||
struct pim_msg_header *header;
|
||||
|
||||
if (len < sizeof(*ip_hdr)) {
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
@ -151,29 +150,10 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
|
||||
ip_hdr = (struct ip *) buf;
|
||||
ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
|
||||
|
||||
if (ip_hdr->ip_p != PIM_IP_PROTO_PIM) {
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug("IP packet protocol=%d is not PIM=%d",
|
||||
ip_hdr->ip_p, PIM_IP_PROTO_PIM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip_hlen < PIM_IP_HEADER_MIN_LEN) {
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug("IP packet header size=%zu shorter than minimum=%d",
|
||||
ip_hlen, PIM_IP_HEADER_MIN_LEN);
|
||||
return -1;
|
||||
}
|
||||
if (ip_hlen > PIM_IP_HEADER_MAX_LEN) {
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug("IP packet header size=%zu greater than maximum=%d",
|
||||
ip_hlen, PIM_IP_HEADER_MAX_LEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pim_msg = buf + ip_hlen;
|
||||
pim_msg_len = len - ip_hlen;
|
||||
|
||||
header = (struct pim_msg_header *)pim_msg;
|
||||
if (pim_msg_len < PIM_PIM_MIN_LEN) {
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug("PIM message size=%d shorter than minimum=%d",
|
||||
@ -181,23 +161,20 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pim_version = PIM_MSG_HDR_GET_VERSION(pim_msg);
|
||||
pim_type = PIM_MSG_HDR_GET_TYPE(pim_msg);
|
||||
|
||||
if (pim_version != PIM_PROTO_VERSION) {
|
||||
if (header->ver != PIM_PROTO_VERSION) {
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d",
|
||||
ifp->name, pim_version);
|
||||
ifp->name, header->ver);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* save received checksum */
|
||||
pim_checksum = PIM_MSG_HDR_GET_CHECKSUM(pim_msg);
|
||||
pim_checksum = header->checksum;
|
||||
|
||||
/* for computing checksum */
|
||||
*(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = 0;
|
||||
header->checksum = 0;
|
||||
|
||||
if (pim_type == PIM_MSG_TYPE_REGISTER)
|
||||
if (header->type == PIM_MSG_TYPE_REGISTER)
|
||||
{
|
||||
/* First 8 byte header checksum */
|
||||
checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN);
|
||||
@ -233,14 +210,14 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
|
||||
pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str));
|
||||
pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, sizeof(dst_str));
|
||||
zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
|
||||
pim_pim_msgtype2str (pim_type), src_str, dst_str, ifp->name,
|
||||
ip_hdr->ip_ttl, pim_version, pim_msg_len, checksum);
|
||||
pim_pim_msgtype2str (header->type), src_str, dst_str, ifp->name,
|
||||
ip_hdr->ip_ttl, header->ver, pim_msg_len, checksum);
|
||||
if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
|
||||
pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len);
|
||||
}
|
||||
}
|
||||
|
||||
switch (pim_type)
|
||||
switch (header->type)
|
||||
{
|
||||
case PIM_MSG_TYPE_HELLO:
|
||||
return pim_hello_recv (ifp,
|
||||
@ -265,7 +242,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
|
||||
__FILE__, __PRETTY_FUNCTION__,
|
||||
pim_type, src_str, ifp->name);
|
||||
header->type, src_str, ifp->name);
|
||||
return -1;
|
||||
}
|
||||
pim_neighbor_timer_reset(neigh, neigh->holdtime);
|
||||
@ -280,7 +257,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
|
||||
if (PIM_DEBUG_PIM_PACKETS)
|
||||
zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
|
||||
__FILE__, __PRETTY_FUNCTION__,
|
||||
pim_type, src_str, ifp->name);
|
||||
header->type, src_str, ifp->name);
|
||||
return -1;
|
||||
}
|
||||
pim_neighbor_timer_reset(neigh, neigh->holdtime);
|
||||
@ -292,7 +269,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
|
||||
default:
|
||||
if (PIM_DEBUG_PIM_PACKETS) {
|
||||
zlog_debug("Recv PIM packet type %d which is not currently understood",
|
||||
pim_type);
|
||||
header->type);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -408,7 +385,6 @@ static void pim_sock_read_on(struct interface *ifp)
|
||||
pim_ifp->pim_sock_fd);
|
||||
}
|
||||
pim_ifp->t_pim_sock_read = NULL;
|
||||
zassert(!pim_ifp->t_pim_sock_read);
|
||||
THREAD_READ_ON(master, pim_ifp->t_pim_sock_read, pim_sock_read, ifp,
|
||||
pim_ifp->pim_sock_fd);
|
||||
}
|
||||
@ -558,7 +534,7 @@ pim_msg_send(int fd, struct in_addr src,
|
||||
unsigned char buffer[10000];
|
||||
unsigned char *msg_start;
|
||||
uint8_t ttl = MAXTTL;
|
||||
enum pim_msg_type pim_type = PIM_MSG_TYPE_HELLO;
|
||||
struct pim_msg_header *header;
|
||||
struct ip *ip;
|
||||
|
||||
memset (buffer, 0, 10000);
|
||||
@ -567,6 +543,7 @@ pim_msg_send(int fd, struct in_addr src,
|
||||
msg_start = buffer + sizeof (struct ip);
|
||||
memcpy (msg_start, pim_msg, pim_msg_size);
|
||||
|
||||
header = (struct pim_msg_header *)pim_msg;
|
||||
/*
|
||||
* Omnios apparently doesn't have a #define for IP default
|
||||
* ttl that is the same as all other platforms.
|
||||
@ -575,8 +552,7 @@ pim_msg_send(int fd, struct in_addr src,
|
||||
#define IPDEFTTL 64
|
||||
#endif
|
||||
/* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
|
||||
pim_type = PIM_MSG_HDR_GET_TYPE (pim_msg);
|
||||
switch (pim_type)
|
||||
switch (header->type)
|
||||
{
|
||||
case PIM_MSG_TYPE_HELLO:
|
||||
case PIM_MSG_TYPE_JOIN_PRUNE:
|
||||
@ -607,12 +583,13 @@ pim_msg_send(int fd, struct in_addr src,
|
||||
ip->ip_len = htons (sendlen);
|
||||
|
||||
if (PIM_DEBUG_PIM_PACKETS) {
|
||||
struct pim_msg_header *header = (struct pim_msg_header *)pim_msg;
|
||||
char dst_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
|
||||
zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
|
||||
__PRETTY_FUNCTION__,
|
||||
dst_str, ifname, pim_msg_size,
|
||||
*(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg));
|
||||
header->checksum);
|
||||
}
|
||||
|
||||
memset(&to, 0, sizeof(to));
|
||||
@ -671,8 +648,7 @@ static int hello_send(struct interface *ifp,
|
||||
zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
|
||||
zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
|
||||
|
||||
pim_msg_build_header(pim_msg, pim_msg_size,
|
||||
PIM_MSG_TYPE_HELLO);
|
||||
pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO);
|
||||
|
||||
if (pim_msg_send(pim_ifp->pim_sock_fd,
|
||||
pim_ifp->primary_address,
|
||||
|
@ -48,15 +48,6 @@ enum pim_msg_type {
|
||||
PIM_MSG_TYPE_CANDIDATE
|
||||
};
|
||||
|
||||
#define PIM_MSG_HDR_OFFSET_VERSION(pim_msg) (pim_msg)
|
||||
#define PIM_MSG_HDR_OFFSET_TYPE(pim_msg) (pim_msg)
|
||||
#define PIM_MSG_HDR_OFFSET_RESERVED(pim_msg) (((char *)(pim_msg)) + 1)
|
||||
#define PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) (((char *)(pim_msg)) + 2)
|
||||
|
||||
#define PIM_MSG_HDR_GET_VERSION(pim_msg) ((*(uint8_t*) PIM_MSG_HDR_OFFSET_VERSION(pim_msg)) >> 4)
|
||||
#define PIM_MSG_HDR_GET_TYPE(pim_msg) ((*(uint8_t*) PIM_MSG_HDR_OFFSET_TYPE(pim_msg)) & 0xF)
|
||||
#define PIM_MSG_HDR_GET_CHECKSUM(pim_msg) (*(uint16_t*) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg))
|
||||
|
||||
void pim_ifstat_reset(struct interface *ifp);
|
||||
void pim_sock_reset(struct interface *ifp);
|
||||
int pim_sock_add(struct interface *ifp);
|
||||
|
@ -184,14 +184,13 @@ static int nexthop_mismatch(const struct pim_nexthop *nh1,
|
||||
(nh1->mrib_route_metric != nh2->mrib_route_metric);
|
||||
}
|
||||
|
||||
enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr)
|
||||
enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old)
|
||||
{
|
||||
struct prefix save_rpf_addr;
|
||||
struct pim_nexthop save_nexthop;
|
||||
struct pim_rpf *rpf = &up->rpf;
|
||||
struct pim_rpf saved;
|
||||
|
||||
save_nexthop = rpf->source_nexthop; /* detect change in pim_nexthop */
|
||||
save_rpf_addr = rpf->rpf_addr; /* detect change in RPF'(S,G) */
|
||||
saved.source_nexthop = rpf->source_nexthop;
|
||||
saved.rpf_addr = rpf->rpf_addr;
|
||||
|
||||
if (pim_nexthop_lookup(&rpf->source_nexthop,
|
||||
up->upstream_addr,
|
||||
@ -211,7 +210,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_
|
||||
}
|
||||
|
||||
/* detect change in pim_nexthop */
|
||||
if (nexthop_mismatch(&rpf->source_nexthop, &save_nexthop)) {
|
||||
if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) {
|
||||
|
||||
if (PIM_DEBUG_ZEBRA) {
|
||||
char nhaddr_str[PREFIX_STRLEN];
|
||||
@ -231,27 +230,29 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_
|
||||
}
|
||||
|
||||
/* detect change in RPF_interface(S) */
|
||||
if (save_nexthop.interface != rpf->source_nexthop.interface) {
|
||||
if (saved.source_nexthop.interface != rpf->source_nexthop.interface) {
|
||||
|
||||
if (PIM_DEBUG_ZEBRA) {
|
||||
zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s",
|
||||
__FILE__, __PRETTY_FUNCTION__,
|
||||
up->sg_str,
|
||||
save_nexthop.interface ? save_nexthop.interface->name : "<oldif?>",
|
||||
saved.source_nexthop.interface ? saved.source_nexthop.interface->name : "<oldif?>",
|
||||
rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<newif?>");
|
||||
/* warning only */
|
||||
}
|
||||
|
||||
pim_upstream_rpf_interface_changed(up, save_nexthop.interface);
|
||||
pim_upstream_rpf_interface_changed(up, saved.source_nexthop.interface);
|
||||
}
|
||||
|
||||
/* detect change in RPF'(S,G) */
|
||||
if (save_rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr) {
|
||||
if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr) {
|
||||
|
||||
/* return old rpf to caller ? */
|
||||
if (old_rpf_addr)
|
||||
*old_rpf_addr = save_rpf_addr.u.prefix4;
|
||||
|
||||
if (old)
|
||||
{
|
||||
old->source_nexthop = saved.source_nexthop;
|
||||
old->rpf_addr = saved.rpf_addr;
|
||||
}
|
||||
return PIM_RPF_CHANGED;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ struct pim_upstream;
|
||||
extern long long nexthop_lookups_avoided;
|
||||
|
||||
int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed);
|
||||
enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct in_addr *old_rpf_addr);
|
||||
enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old);
|
||||
|
||||
int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf);
|
||||
int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf);
|
||||
|
@ -316,27 +316,34 @@ int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr
|
||||
int
|
||||
pim_static_write_mroute (struct vty *vty, struct interface *ifp)
|
||||
{
|
||||
struct pim_interface *pim_ifp = ifp->info;
|
||||
struct listnode *node;
|
||||
struct static_route *sroute;
|
||||
int count = 0;
|
||||
char sbuf[INET_ADDRSTRLEN];
|
||||
char gbuf[INET_ADDRSTRLEN];
|
||||
|
||||
if (!pim_ifp)
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_static_route_list, node, sroute))
|
||||
{
|
||||
pim_inet4_dump ("<ifaddr?>", sroute->group, gbuf, sizeof (gbuf));
|
||||
pim_inet4_dump ("<ifaddr?>", sroute->source, sbuf, sizeof (sbuf));
|
||||
if (sroute->iif == ifp->ifindex)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAXVIFS; i++)
|
||||
if (sroute->oif_ttls[i])
|
||||
{
|
||||
struct interface *oifp = if_lookup_by_index (i);
|
||||
vty_out (vty, " ip mroute %s %s %s%s", oifp->name, gbuf, sbuf, VTY_NEWLINE);
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
if (sroute->iif == pim_ifp->mroute_vif_index)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAXVIFS; i++)
|
||||
if (sroute->oif_ttls[i])
|
||||
{
|
||||
struct interface *oifp = pim_if_find_by_vif_index (i);
|
||||
if (sroute->source.s_addr == 0)
|
||||
vty_out (vty, " ip mroute %s %s%s", oifp->name, gbuf, VTY_NEWLINE);
|
||||
else
|
||||
vty_out (vty, " ip mroute %s %s %s%s", oifp->name, gbuf, sbuf, VTY_NEWLINE);
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -171,9 +171,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
|
||||
THREAD_OFF(up->t_msdp_reg_timer);
|
||||
|
||||
if (up->join_state == PIM_UPSTREAM_JOINED) {
|
||||
pim_joinprune_send (up->rpf.source_nexthop.interface,
|
||||
up->rpf.rpf_addr.u.prefix4,
|
||||
up, 0);
|
||||
pim_joinprune_send (&up->rpf, up, 0);
|
||||
if (up->sg.src.s_addr == INADDR_ANY) {
|
||||
/* if a (*, G) entry in the joined state is being deleted we
|
||||
* need to notify MSDP */
|
||||
@ -231,10 +229,7 @@ pim_upstream_send_join (struct pim_upstream *up)
|
||||
}
|
||||
|
||||
/* send Join(S,G) to the current upstream neighbor */
|
||||
pim_joinprune_send(up->rpf.source_nexthop.interface,
|
||||
up->rpf.rpf_addr.u.prefix4,
|
||||
up,
|
||||
1 /* join */);
|
||||
pim_joinprune_send(&up->rpf, up, 1 /* join */);
|
||||
}
|
||||
|
||||
static int on_join_timer(struct thread *t)
|
||||
@ -334,8 +329,7 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
|
||||
}
|
||||
|
||||
void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
|
||||
struct pim_upstream *up,
|
||||
struct in_addr rpf_addr)
|
||||
struct pim_upstream *up)
|
||||
{
|
||||
long join_timer_remain_msec;
|
||||
int t_override_msec;
|
||||
@ -345,7 +339,7 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
|
||||
|
||||
if (PIM_DEBUG_TRACE) {
|
||||
char rpf_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str));
|
||||
pim_inet4_dump("<rpf?>", up->rpf.rpf_addr.u.prefix4, rpf_str, sizeof(rpf_str));
|
||||
zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec",
|
||||
debug_label,
|
||||
up->sg_str, rpf_str,
|
||||
@ -488,10 +482,7 @@ pim_upstream_switch(struct pim_upstream *up,
|
||||
forward_off(up);
|
||||
if (old_state == PIM_UPSTREAM_JOINED)
|
||||
pim_msdp_up_join_state_changed(up);
|
||||
pim_joinprune_send(up->rpf.source_nexthop.interface,
|
||||
up->rpf.rpf_addr.u.prefix4,
|
||||
up,
|
||||
0 /* prune */);
|
||||
pim_joinprune_send(&up->rpf, up, 0 /* prune */);
|
||||
if (up->t_join_timer)
|
||||
THREAD_OFF(up->t_join_timer);
|
||||
}
|
||||
@ -662,7 +653,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
|
||||
return up;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
|
||||
struct pim_ifchannel *ch)
|
||||
{
|
||||
@ -803,7 +794,7 @@ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr)
|
||||
continue;
|
||||
|
||||
pim_upstream_join_timer_decrease_to_t_override("RPF'(S,G) GenID change",
|
||||
up, neigh_addr);
|
||||
up);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,14 +129,17 @@ struct pim_upstream *pim_upstream_add (struct prefix_sg *sg,
|
||||
void pim_upstream_del(struct pim_upstream *up, const char *name);
|
||||
|
||||
int pim_upstream_evaluate_join_desired(struct pim_upstream *up);
|
||||
int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
|
||||
struct pim_ifchannel *ch);
|
||||
void pim_upstream_update_join_desired(struct pim_upstream *up);
|
||||
|
||||
void pim_upstream_join_suppress(struct pim_upstream *up,
|
||||
struct in_addr rpf_addr,
|
||||
int holdtime);
|
||||
|
||||
void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
|
||||
struct pim_upstream *up,
|
||||
struct in_addr rpf_addr);
|
||||
struct pim_upstream *up);
|
||||
|
||||
void pim_upstream_join_timer_restart(struct pim_upstream *up);
|
||||
void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr);
|
||||
void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
|
||||
|
@ -366,12 +366,11 @@ static void scan_upstream_rpf_cache()
|
||||
struct pim_upstream *up;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) {
|
||||
struct in_addr old_rpf_addr;
|
||||
struct interface *old_interface;
|
||||
enum pim_rpf_result rpf_result;
|
||||
struct pim_rpf old;
|
||||
|
||||
old_interface = up->rpf.source_nexthop.interface;
|
||||
rpf_result = pim_rpf_update(up, &old_rpf_addr);
|
||||
old.source_nexthop.interface = up->rpf.source_nexthop.interface;
|
||||
rpf_result = pim_rpf_update(up, &old);
|
||||
if (rpf_result == PIM_RPF_FAILURE)
|
||||
continue;
|
||||
|
||||
@ -412,14 +411,10 @@ static void scan_upstream_rpf_cache()
|
||||
|
||||
|
||||
/* send Prune(S,G) to the old upstream neighbor */
|
||||
pim_joinprune_send(old_interface, old_rpf_addr,
|
||||
up, 0 /* prune */);
|
||||
pim_joinprune_send(&old, up, 0 /* prune */);
|
||||
|
||||
/* send Join(S,G) to the current upstream neighbor */
|
||||
pim_joinprune_send(up->rpf.source_nexthop.interface,
|
||||
up->rpf.rpf_addr.u.prefix4,
|
||||
up,
|
||||
1 /* join */);
|
||||
pim_joinprune_send(&up->rpf, up, 1 /* join */);
|
||||
|
||||
pim_upstream_join_timer_restart(up);
|
||||
} /* up->join_state == PIM_UPSTREAM_JOINED */
|
||||
|
32
pimd/pimd.h
32
pimd/pimd.h
@ -31,13 +31,41 @@
|
||||
#define PIMD_DEFAULT_CONFIG "pimd.conf"
|
||||
#define PIMD_VTY_PORT 2611
|
||||
|
||||
#define PIM_IP_HEADER_MIN_LEN (20)
|
||||
#define PIM_IP_HEADER_MAX_LEN (60)
|
||||
#define PIM_IP_PROTO_IGMP (2)
|
||||
#define PIM_IP_PROTO_PIM (103)
|
||||
#define PIM_IGMP_MIN_LEN (8)
|
||||
|
||||
/*
|
||||
* PIM MSG Header Format
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |PIM Ver| Type | Reserved | Checksum |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
#define PIM_MSG_HEADER_LEN (4)
|
||||
#define PIM_PIM_MIN_LEN PIM_MSG_HEADER_LEN
|
||||
|
||||
#define PIM_ENCODED_IPV4_UCAST_SIZE (6)
|
||||
#define PIM_ENCODED_IPV4_GROUP_SIZE (8)
|
||||
#define PIM_ENCODED_IPV4_SOURCE_SIZE (8)
|
||||
|
||||
/*
|
||||
* J/P Message Format, Group Header
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Upstream Neighbor Address (Encoded-Unicast format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Reserved | Num groups | Holdtime |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Multicast Group Address 1 (Encoded-Group format) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Number of Joined Sources | Number of Pruned Sources |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
#define PIM_JP_GROUP_HEADER_SIZE (PIM_ENCODED_IPV4_UCAST_SIZE + \
|
||||
1 + 1 + 2 + \
|
||||
PIM_ENCODED_IPV4_GROUP_SIZE + \
|
||||
2 + 2)
|
||||
|
||||
#define PIM_PROTO_VERSION (2)
|
||||
|
||||
#define MCAST_ALL_SYSTEMS "224.0.0.1"
|
||||
|
Loading…
Reference in New Issue
Block a user