Merge pull request #224 from donaldsharp/pim_patches_feb

Pim patches feb
This commit is contained in:
Russ White 2017-03-01 09:52:24 -05:00 committed by GitHub
commit 54b19ceaf9
22 changed files with 514 additions and 439 deletions

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */

View File

@ -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];

View File

@ -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,

View File

@ -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;
}

View File

@ -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 */

View File

@ -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));

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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 */

View File

@ -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"