From 811ed42ae52578d75421f6b0bd03c1843db9829e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 9 Feb 2017 12:53:00 -0500 Subject: [PATCH 01/20] pimd: Convert sizes to #defines Convert the const int size of the encoded types to #defines so that they can be used elsewhere. Return Null instead of 0. Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 24 +++++++++--------------- pimd/pimd.h | 4 ++++ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index ab14b3ae5f..339e21ad38 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -72,27 +72,23 @@ uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, int buf_size, struct in_addr addr) { - const int ENCODED_IPV4_UCAST_SIZE = 6; - - if (buf_size < ENCODED_IPV4_UCAST_SIZE) { - return 0; + if (buf_size < PIM_ENCODED_IPV4_UCAST_SIZE) { + return NULL; } 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) { - const int ENCODED_IPV4_GROUP_SIZE = 8; - - if (buf_size < ENCODED_IPV4_GROUP_SIZE) { - return 0; + if (buf_size < PIM_ENCODED_IPV4_GROUP_SIZE) { + return NULL; } buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ @@ -101,17 +97,15 @@ uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, 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) { - const int ENCODED_IPV4_SOURCE_SIZE = 8; - - if (buf_size < ENCODED_IPV4_SOURCE_SIZE) { - return 0; + if (buf_size < PIM_ENCODED_IPV4_SOURCE_SIZE) { + return NULL; } buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ @@ -120,7 +114,7 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, 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 diff --git a/pimd/pimd.h b/pimd/pimd.h index 1f8dcdfb29..f7cc132ee3 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -38,6 +38,10 @@ #define PIM_IGMP_MIN_LEN (8) #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) #define PIM_PROTO_VERSION (2) #define MCAST_ALL_SYSTEMS "224.0.0.1" From 09778298e231208c5862c62ca0096c9f0101e446 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 9 Feb 2017 13:13:07 -0500 Subject: [PATCH 02/20] pimd: Document the J/P packet format a bit better. Document the J/P packet format and ensure that the smallest size packet that we may send will actually fit. Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 87 +++++++++++++++++++++++++++++++++++++++++++------- pimd/pimd.h | 26 +++++++++++++++ 2 files changed, 101 insertions(+), 12 deletions(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 339e21ad38..e8b1b5a622 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -117,6 +117,72 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; } +/* + * 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, int buf_size, int is_join, struct pim_upstream *up, @@ -130,6 +196,15 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, struct in_addr stosend; uint8_t bits; int remain; + int min_len = PIM_MSG_HEADER_LEN + PIM_JP_GROUP_HEADER_SIZE + + PIM_ENCODED_IPV4_SOURCE_SIZE; // Only 1 source + + if (buf_size < min_len) + { + zlog_warn ("%s: Buffer size specified(%d) will not hold smallest J/P Message Possible\n", + __PRETTY_FUNCTION__, buf_size); + return -2; + } remain = end - pim_msg_curr; pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, buf_size - PIM_MSG_HEADER_LEN, upstream); @@ -141,13 +216,6 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, return -3; } - 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 */ @@ -169,11 +237,6 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, } 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; diff --git a/pimd/pimd.h b/pimd/pimd.h index f7cc132ee3..2e75eea361 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -36,12 +36,38 @@ #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" From 70ce34ae66184d4b456f45e6544c5fc0c350f2e5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 9 Feb 2017 13:47:42 -0500 Subject: [PATCH 03/20] pimd: Add 'struct pim_msg_header' packed data structure. Add the 'struct pim_msg_header' and convert all places that encoded/decoded the message header to use it. Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 19 +++++++------------ pimd/pim_msg.h | 10 ++++++++++ pimd/pim_pim.c | 38 ++++++++++++++++++-------------------- pimd/pim_pim.h | 9 --------- 4 files changed, 35 insertions(+), 41 deletions(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index e8b1b5a622..97b9688aff 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -40,32 +40,27 @@ void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size, uint8_t pim_msg_type) { - uint16_t checksum; + struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; zassert(pim_msg_size >= PIM_PIM_MIN_LEN); /* * 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, diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 5229f85c72..04a6a01e5c 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -35,6 +35,16 @@ */ #define PIM_MSG_ADDRESS_FAMILY_IPV4 (1) +/* + * 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)); + 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, diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index e4c654557a..dd0071d419 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -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) @@ -174,6 +173,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) 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 +181,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 +230,14 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); pim_inet4_dump("", 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 +262,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 +277,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 +289,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; } @@ -558,7 +555,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 +564,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 +573,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 +604,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_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)); diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 00c5f9012e..690b6c05cd 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -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); From f8e7d7992fe201052e3969bdd4aab217ffd4d505 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Feb 2017 13:46:52 -0500 Subject: [PATCH 04/20] pimd: Assume buffer size passed in is of sufficient size For: pim_msg_build_header pim_msg_addr_encode_ipv4_ucast pim_msg_addr_encode_ipv4_group pim_msg_addr_encode_ipv4_source Assume that the buffer size passed in is of sufficient size already. This is assured already because buffer sizes are checked for minimum lengths for the entire packet ahead of time. So we are double checking. Additionally at scale we will be calling these functions a very very large number of times. Signed-off-by: Donald Sharp --- pimd/pim_assert.c | 8 ++----- pimd/pim_msg.c | 59 ++++++++++++++--------------------------------- pimd/pim_msg.h | 21 ++++++----------- pimd/pim_pim.c | 3 +-- 4 files changed, 27 insertions(+), 64 deletions(-) diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index d6f372cc44..f2bfb846dd 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -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("", 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("", source_addr, source_str, sizeof(source_str)); diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 97b9688aff..4378ac99f7 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -37,13 +37,10 @@ #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) { struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; - zassert(pim_msg_size >= PIM_PIM_MIN_LEN); - /* * Write header */ @@ -63,14 +60,8 @@ void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size, 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) { - if (buf_size < PIM_ENCODED_IPV4_UCAST_SIZE) { - return NULL; - } - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ buf[1] = '\0'; /* native encoding */ memcpy(buf+2, &addr, sizeof(struct in_addr)); @@ -78,14 +69,8 @@ uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, 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) { - if (buf_size < PIM_ENCODED_IPV4_GROUP_SIZE) { - return NULL; - } - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ buf[1] = '\0'; /* native encoding */ buf[2] = '\0'; /* reserved */ @@ -96,13 +81,9 @@ uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, } 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) { - if (buf_size < PIM_ENCODED_IPV4_SOURCE_SIZE) { - return NULL; - } - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ buf[1] = '\0'; /* native encoding */ buf[2] = bits; @@ -179,7 +160,7 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, int buf_size, * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ int -pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, +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) { @@ -191,23 +172,18 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, struct in_addr stosend; uint8_t bits; int remain; - int min_len = PIM_MSG_HEADER_LEN + PIM_JP_GROUP_HEADER_SIZE + + size_t min_len = PIM_MSG_HEADER_LEN + PIM_JP_GROUP_HEADER_SIZE + PIM_ENCODED_IPV4_SOURCE_SIZE; // Only 1 source - if (buf_size < min_len) - { - zlog_warn ("%s: Buffer size specified(%d) will not hold smallest J/P Message Possible\n", - __PRETTY_FUNCTION__, buf_size); - return -2; - } + assert(buf_size > min_len); remain = end - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, buf_size - PIM_MSG_HEADER_LEN, upstream); + pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, upstream); if (!pim_msg_curr) { char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream, dst_str, sizeof(dst_str)); - zlog_warn("%s: failure encoding destination address %s: space left=%d", - __PRETTY_FUNCTION__, dst_str, remain); + zlog_warn("%s: failure encoding destination address %s", + __PRETTY_FUNCTION__, dst_str); return -3; } @@ -221,13 +197,12 @@ pim_msg_join_prune_encode (uint8_t *buf, int buf_size, int is_join, ++pim_msg_curr; remain = end - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_group (pim_msg_curr, remain, - up->sg.grp); + pim_msg_curr = pim_msg_addr_encode_ipv4_group (pim_msg_curr, up->sg.grp); if (!pim_msg_curr) { char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", up->sg.grp, group_str, sizeof(group_str)); - zlog_warn("%s: failure encoding group address %s: space left=%d", - __PRETTY_FUNCTION__, group_str, remain); + zlog_warn("%s: failure encoding group address %s", + __PRETTY_FUNCTION__, group_str); return -5; } @@ -257,12 +232,12 @@ 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); + pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, stosend, bits); if (!pim_msg_curr) { char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); - zlog_warn("%s: failure encoding source address %s: space left=%d", - __PRETTY_FUNCTION__, source_str, remain); + zlog_warn("%s: failure encoding source address %s", + __PRETTY_FUNCTION__, source_str); return -7; } remain = pim_msg_curr - pim_msg; diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 04a6a01e5c..3be37ac368 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -45,25 +45,18 @@ struct pim_msg_header { uint16_t checksum; } __attribute__ ((packed)); -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); +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 */ diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index dd0071d419..b81b1b01a7 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -669,8 +669,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, From 74ac496fcbf976bebaa76728090c68c74865a66d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Feb 2017 14:05:42 -0500 Subject: [PATCH 05/20] pimd: Add packed data structures for building j/p messages Switch pim over to using packed data structures for building Join/Prune messages to be sent. This is a pre-cursor to the ability to handle the ability to aggregate Join/Prune messages together. Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 166 ++++++++++++++++++++----------------------------- pimd/pim_msg.h | 38 +++++++++++ 2 files changed, 107 insertions(+), 97 deletions(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 4378ac99f7..3a8ccb887e 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -161,25 +161,16 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, */ 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_upstream *up, + struct in_addr upstream, int holdtime) { - 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 pim_jp *msg = (struct pim_jp *)buf; struct in_addr stosend; uint8_t bits; - int remain; - size_t min_len = PIM_MSG_HEADER_LEN + PIM_JP_GROUP_HEADER_SIZE + - PIM_ENCODED_IPV4_SOURCE_SIZE; // Only 1 source - assert(buf_size > min_len); + assert(buf_size > sizeof (struct pim_jp)); - remain = end - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast (pim_msg_curr, upstream); - if (!pim_msg_curr) { + if (!pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, upstream)) { char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("", upstream, dst_str, sizeof(dst_str)); zlog_warn("%s: failure encoding destination address %s", @@ -187,40 +178,22 @@ pim_msg_join_prune_encode (uint8_t *buf, size_t buf_size, int is_join, return -3; } - *pim_msg_curr = 0; /* reserved */ - ++pim_msg_curr; - *pim_msg_curr = 1; /* number of groups */ - ++pim_msg_curr; + msg->reserved = 0; + msg->num_groups = 1; + msg->holdtime = htons(holdtime); - *((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, up->sg.grp); - if (!pim_msg_curr) { + if (!pim_msg_addr_encode_ipv4_group ((uint8_t *)&msg->groups[0].g, up->sg.grp)) { char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("", up->sg.grp, group_str, sizeof(group_str)); zlog_warn("%s: failure encoding group address %s", - __PRETTY_FUNCTION__, group_str); + __PRETTY_FUNCTION__, group_str); return -5; } - remain = end - pim_msg_curr; + /* number of joined/pruned sources */ + msg->groups[0].joins = htons(is_join ? 1 : 0); + msg->groups[0].prunes = htons(is_join ? 0 : 1); - /* 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); @@ -232,15 +205,14 @@ pim_msg_join_prune_encode (uint8_t *buf, size_t 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, stosend, bits); - if (!pim_msg_curr) { + + if (!pim_msg_addr_encode_ipv4_source ((uint8_t *)&msg->groups[0].s[0], stosend, bits)) { char source_str[INET_ADDRSTRLEN]; pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); zlog_warn("%s: failure encoding source address %s", - __PRETTY_FUNCTION__, source_str); + __PRETTY_FUNCTION__, source_str); return -7; } - remain = pim_msg_curr - pim_msg; /* * This is not implemented correctly at this point in time @@ -254,61 +226,61 @@ pim_msg_join_prune_encode (uint8_t *buf, size_t 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); + pim_msg_build_header (buf, sizeof (struct pim_jp), PIM_MSG_TYPE_JOIN_PRUNE); - return remain; + return sizeof (struct pim_jp); } diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 3be37ac368..3af8486d5d 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -45,6 +45,44 @@ struct pim_msg_header { 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); From c48a612c21bce760d4943effde1b79e395a03607 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Feb 2017 15:04:17 -0500 Subject: [PATCH 06/20] pimd: Remove unneeded parameter pim_upstream_join_timer_decrease_to_t_override passed in a `struct in_addr` that in all cases was part of the upstream data structure that was passed in already. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 9 +++------ pimd/pim_upstream.c | 7 +++---- pimd/pim_upstream.h | 5 +++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index f0e4a3a68a..3caac4cda6 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -665,20 +665,17 @@ 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, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 4ae49c0fd4..4f63b20da5 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -334,8 +334,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 +344,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_addr, rpf_str, sizeof(rpf_str)); + pim_inet4_dump("", 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, @@ -803,7 +802,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); } } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 1a50c0c6e3..271f2dfbde 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -134,9 +134,10 @@ 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, From 116b989af23a1232b3df7015c4b7ce124b04f84a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Feb 2017 15:14:16 -0500 Subject: [PATCH 07/20] pimd: Only debug in the unusual case When receiving a J/P packet, only check to see if we should log when the J/P packet is not for us. Very slight performance improvement additionally Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 3caac4cda6..0b5baf9756 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -678,12 +678,13 @@ static void check_recv_upstream(int is_join, 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 */ @@ -692,27 +693,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, 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, 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 */ } From 910dad7e9927d20043209892eb43c3007b4ae2d7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Feb 2017 15:26:41 -0500 Subject: [PATCH 08/20] pimd: Remove unnecessary check in packet process path When we get a packet from the network for pim, we do not need to check to see that it is a pim packet, since that is what we've asked to receive. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index b81b1b01a7..e5d5971ce2 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -150,13 +150,6 @@ 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", From b50fcf3aa8f1fa9db49273de6723c56953868eca Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Feb 2017 15:48:42 -0500 Subject: [PATCH 09/20] pimd: Remove unnecessary ip header length checks on receipt. The kernel will not hand us a malformed packet. Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 11 ----------- pimd/pim_pim.c | 13 ------------- pimd/pimd.h | 2 -- 3 files changed, 26 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 24b9e54ea5..74a05b8589 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -434,17 +434,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) 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; diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index e5d5971ce2..e852a88fee 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -150,19 +150,6 @@ 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_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; diff --git a/pimd/pimd.h b/pimd/pimd.h index 2e75eea361..0da8452ab5 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -31,8 +31,6 @@ #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) From 0ae2a75af4215c358b6876054129fac92439338b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Feb 2017 15:54:23 -0500 Subject: [PATCH 10/20] pimd: Remove unnecessary igmp check When we receive a igmp packet, there is no need to ensure that it is a igmp packet, as that is what we have asked for. Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 74a05b8589..b23fd73518 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -428,12 +428,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; - } - igmp_msg = buf + ip_hlen; msg_type = *igmp_msg; igmp_msg_len = len - ip_hlen; From 9f44d04202ddfcc3df63c6d542720163fba21a76 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Feb 2017 06:53:00 -0500 Subject: [PATCH 11/20] pimd: Narrow inheritance search down to interface we are interested in. When we are only looking at one ifchannel, for inheritance, narrow the search down to only the interface/ifchannel we are interested in Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 4 ++-- pimd/pim_ifchannel.h | 1 + pimd/pim_upstream.c | 2 +- pimd/pim_upstream.h | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 0b5baf9756..6bff65c1ad 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -969,7 +969,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); @@ -1016,7 +1016,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); /* diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index a3dc0e9d83..5cac0318c6 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -26,6 +26,7 @@ #include "if.h" #include "prefix.h" +struct pim_ifchannel; #include "pim_upstream.h" enum pim_ifmembership { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 4f63b20da5..b7526c290a 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -661,7 +661,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) { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 271f2dfbde..f36b6fba8b 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -129,6 +129,8 @@ 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, From 4961e0ad8f7e1183d8df0b38358882caecbab63e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Feb 2017 06:54:56 -0500 Subject: [PATCH 12/20] pimd: Trust the compiler When we set a variable to NULL, there is no need to assert on it the following line. Signed-off-by: Donald Sharp --- pimd/pim_pim.c | 1 - 1 file changed, 1 deletion(-) diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index e852a88fee..471d8aa39e 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -385,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); } From a625e9373be06671b0b9e3cafb026dec5a0cb9b5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 12 Feb 2017 20:16:08 -0500 Subject: [PATCH 13/20] pimd: Make ifchannel lookup a hash lookup When we are at scale, it is possible that we have a very large number of ifchannels per interface. So make lookup for that situation to be a hash lookup. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 10 ++++++++++ pimd/pim_iface.h | 1 + pimd/pim_ifchannel.c | 43 ++++++++++++++++++++++++++++++------------- pimd/pim_ifchannel.h | 3 +++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index c1289a3ba7..8f7d40bb36 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -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; diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 244de598db..7c0d57a5d1 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -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; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 6bff65c1ad..021e43a4ad 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -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; @@ -1228,3 +1224,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; +} diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 5cac0318c6..c7084034a0 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -154,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 */ From d270b2163e28a62e9e7ff812e203d5adf40dbf5e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 13 Feb 2017 14:18:48 -0500 Subject: [PATCH 14/20] pimd: Refactor functions Refactor the add and delete functions. Signed-off-by: Donald Sharp --- pimd/pim_oil.c | 84 +++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 4c5eff4883..3e9d6c5a89 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -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); } } From 42a0111b64018c15b2d3bf71faf384d29113e31a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 14 Feb 2017 10:41:28 -0500 Subject: [PATCH 15/20] pimd: Refactor pim_rpf_update to take a 'struct pim_rpf' Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 27 ++++++++++++++------------- pimd/pim_rpf.h | 2 +- pimd/pim_zebra.c | 9 ++++----- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index ae00e347b5..40e035c3f4 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -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 : "", + saved.source_nexthop.interface ? saved.source_nexthop.interface->name : "", rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""); /* 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; } diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index bb77775324..51e84b4593 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -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); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 1bb4852c6b..b96d812a62 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -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,7 +411,7 @@ static void scan_upstream_rpf_cache() /* send Prune(S,G) to the old upstream neighbor */ - pim_joinprune_send(old_interface, old_rpf_addr, + pim_joinprune_send(old.source_nexthop.interface, old.rpf_addr.u.prefix4, up, 0 /* prune */); /* send Join(S,G) to the current upstream neighbor */ From b5e2377cca8d2e7339927389e6f05a2f4a1e209d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 14 Feb 2017 12:23:28 -0500 Subject: [PATCH 16/20] pimd: Refactor pim_joinprune_send Refactor pim_joinprune_send to use 'struct rpf' Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 9 +++++++-- pimd/pim_join.c | 36 ++++++++++++++++-------------------- pimd/pim_join.h | 7 +++---- pimd/pim_upstream.c | 14 +++----------- pimd/pim_zebra.c | 8 ++------ 5 files changed, 31 insertions(+), 43 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 021e43a4ad..891bdc448d 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -597,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 { diff --git a/pimd/pim_join.c b/pimd/pim_join.c index cedce8165c..783dd75075 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -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("", upstream_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", 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("", upstream_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", 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; } diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 1eeeef756f..4b76166328 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -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 */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b7526c290a..1712acaa1e 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -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) @@ -487,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); } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b96d812a62..0f92b4a7b0 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -411,14 +411,10 @@ static void scan_upstream_rpf_cache() /* send Prune(S,G) to the old upstream neighbor */ - pim_joinprune_send(old.source_nexthop.interface, old.rpf_addr.u.prefix4, - 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 */ From b7ddd2ec481969bdfcd576c52a6e99c4489ece58 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 14 Feb 2017 20:03:18 -0500 Subject: [PATCH 17/20] pimd: Intelligently drop wrvifwhole packets in some cases Suppose we have this (*,G) IIF = swp1 OIL: swp3 (S,G) IIF = swp2 OIL: swp3 swp4 There exists situations where we can receive the mcast packet for (S,G) on both swp1 and swp2. In this case the packet received on swp1 will be sent from the kernel to us as a WRVIF and WRVIFWHOLE. As per normal, WRVIF packet processing handles the assert case so we know we have not received the packet on a downstream interface, so no assert. The WRVIFWHOLE packet processing can then check to see if it received the packet as a result of the (*,G) mroute from upstream. If we have then we can safely drop the packet. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 4fae5b3ca5..ae5d0e9891 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -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)); From 6345a326717472602d2c395e7c2870279be11c57 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 14 Feb 2017 20:45:31 -0500 Subject: [PATCH 18/20] pimd: Add hash lookup for igmp group's When we receive a group in a IGMP report let's look it up based upon a hash instead of a list. Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 38 ++++++++++++++++++++++++++++++++------ pimd/pim_igmp.h | 1 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index b23fd73518..e6582e2b17 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -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" @@ -713,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); } @@ -733,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); } @@ -773,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) @@ -802,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; @@ -1012,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, @@ -1088,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]; diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 802f1ba471..9c569bbd20 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -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, From 79bdcd99745ae16ee57b98bac5477f8bd6d20d4e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 14 Feb 2017 21:32:16 -0500 Subject: [PATCH 19/20] pimd: Move group handling to it's own function for J/P message When we are handling a J/P message, move the group handling to it's own function. Signed-off-by: Donald Sharp --- pimd/pim_msg.c | 192 ++++++++++++++++++++++++++----------------------- 1 file changed, 101 insertions(+), 91 deletions(-) diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 3a8ccb887e..e6b13f3121 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -93,6 +93,106 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; } +static size_t +pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_upstream *up, int is_join) +{ + struct in_addr stosend; + uint8_t bits; + + /* number of joined/pruned sources */ + grp->joins = htons(is_join ? 1 : 0); + grp->prunes = htons(is_join ? 0 : 1); + + if (up->sg.src.s_addr == INADDR_ANY) + { + struct pim_rpf *rpf = pim_rp_g (up->sg.grp); + bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; + stosend = rpf->rpf_addr.u.prefix4; + } + else + { + bits = PIM_ENCODE_SPARSE_BIT; + stosend = up->sg.src; + } + + if (!pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[0], stosend, bits)) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); + zlog_warn("%s: failure encoding source address %s", + __PRETTY_FUNCTION__, source_str); + return 0; + } + + /* + * This is not implemented correctly at this point in time + * Make it stop. + */ +#if 0 + if (up->sg.src.s_addr == INADDR_ANY) + { + struct pim_upstream *child; + struct listnode *up_node; + int send_prune = 0; + + zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", + __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; + } + } + } +#endif + + return sizeof (*grp); +} + /* * J/P Message Format * @@ -165,8 +265,6 @@ pim_msg_join_prune_encode (uint8_t *buf, size_t buf_size, int is_join, struct in_addr upstream, int holdtime) { struct pim_jp *msg = (struct pim_jp *)buf; - struct in_addr stosend; - uint8_t bits; assert(buf_size > sizeof (struct pim_jp)); @@ -190,96 +288,8 @@ pim_msg_join_prune_encode (uint8_t *buf, size_t buf_size, int is_join, return -5; } - /* number of joined/pruned sources */ - msg->groups[0].joins = htons(is_join ? 1 : 0); - msg->groups[0].prunes = htons(is_join ? 0 : 1); + pim_msg_build_jp_groups (&msg->groups[0], up, is_join); - if (up->sg.src.s_addr == INADDR_ANY) - { - struct pim_rpf *rpf = pim_rp_g (up->sg.grp); - bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; - stosend = rpf->rpf_addr.u.prefix4; - } - else - { - bits = PIM_ENCODE_SPARSE_BIT; - stosend = up->sg.src; - } - - if (!pim_msg_addr_encode_ipv4_source ((uint8_t *)&msg->groups[0].s[0], stosend, bits)) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); - zlog_warn("%s: failure encoding source address %s", - __PRETTY_FUNCTION__, source_str); - return -7; - } - - /* - * This is not implemented correctly at this point in time - * Make it stop. - */ -#if 0 - if (up->sg.src.s_addr == INADDR_ANY) - { - struct pim_upstream *child; - struct listnode *up_node; - int send_prune = 0; - - zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", - __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; - } - } - } -#endif pim_msg_build_header (buf, sizeof (struct pim_jp), PIM_MSG_TYPE_JOIN_PRUNE); return sizeof (struct pim_jp); From ce9531309c1298ad3da65a4f29b2f835e812131c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Feb 2017 10:29:15 -0500 Subject: [PATCH 20/20] pimd: Get Static mroutes displaying again The static mroutes were making the assumption that the vif index and the ifindex were the same. This is not necessarily the case. Additionally if we are displaying a *,G route only display the G. Signed-off-by: Donald Sharp --- pimd/pim_static.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/pimd/pim_static.c b/pimd/pim_static.c index e1ccec387a..daaa95ab57 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -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 ("", sroute->group, gbuf, sizeof (gbuf)); pim_inet4_dump ("", 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;