X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fvnet%2Fip%2Figmp_packet.h;h=cd4a40d77ff8a2cb99c3404a309fb0ce897704a3;hb=947ea62;hp=a8e9db6d9ab88fc8ed6007199426e869a03d65d4;hpb=dd47ecadcf63772a6037a1bb3715772d80e87f51;p=vpp.git diff --git a/src/vnet/ip/igmp_packet.h b/src/vnet/ip/igmp_packet.h index a8e9db6d9ab..cd4a40d77ff 100644 --- a/src/vnet/ip/igmp_packet.h +++ b/src/vnet/ip/igmp_packet.h @@ -63,32 +63,46 @@ typedef enum #define _(n,f) IGMP_TYPE_##f = n, foreach_igmp_type #undef _ -} igmp_type_t; +} __attribute__ ((packed)) igmp_type_t; typedef struct { - igmp_type_t type:8; + igmp_type_t type; u8 code; u16 checksum; } igmp_header_t; -typedef struct +/** + * Calculate the maximum response time allowed from the header. + * - RFC 3367 Section 4.1.1 + */ +always_inline f64 +igmp_header_get_max_resp_time (const igmp_header_t * header) { - /* membership_query, version <= 2 reports. */ - igmp_header_t header; + f64 qqi; - /* Multicast destination address. */ - ip4_address_t dst; -} igmp_message_t; + if (header->code < 128) + qqi = header->code; + else + { + u8 mant = header->code << 4; + u8 exp = (header->code & 0x7) << 1; + + qqi = ((mant | 0x10) << (exp + 3)); + } + + /* Querier's Query Interval (QQI), is represented in units of seconds */ + return (qqi / 10); +} typedef struct { /* type 0x11 (IGMPv3) */ igmp_header_t header; - ip4_address_t dst; + ip4_address_t group_address; /* Reserved, Suppress Router-Side Processing flag and Querier's Robustness Variable RRRRSQQQ. */ @@ -101,11 +115,25 @@ typedef struct ip4_address_t src_addresses[0]; } igmp_membership_query_v3_t; +always_inline u32 +igmp_membership_query_v3_length (const igmp_membership_query_v3_t * q) +{ + return (sizeof (*q) + + (sizeof (ip4_address_t) * + clib_net_to_host_u16 (q->n_src_addresses))); +} + +always_inline int +igmp_membership_query_v3_is_geeral (const igmp_membership_query_v3_t * q) +{ + return (0 == q->group_address.as_u32); +} + #define foreach_igmp_membership_group_v3_type \ - _ (1, mode_is_filter_include) \ - _ (2, mode_is_filter_exclude) \ - _ (3, change_to_filter_include) \ - _ (4, change_to_filter_exclude) \ + _ (1, mode_is_include) \ + _ (2, mode_is_exclude) \ + _ (3, change_to_include) \ + _ (4, change_to_exclude) \ _ (5, allow_new_sources) \ _ (6, block_old_sources) @@ -114,11 +142,11 @@ typedef enum #define _(n,f) IGMP_MEMBERSHIP_GROUP_##f = n, foreach_igmp_membership_group_v3_type #undef _ -} igmp_membership_group_v3_type_t; +} __attribute__ ((packed)) igmp_membership_group_v3_type_t; typedef struct { - igmp_membership_group_v3_type_t type:8; + igmp_membership_group_v3_type_t type; /* Number of 32 bit words of aux data after source addresses. */ u8 n_aux_u32s; @@ -126,12 +154,20 @@ typedef struct /* Number of source addresses that follow. */ u16 n_src_addresses; - /* Destination multicast address. */ - ip4_address_t dst_address; + /* Destination multicast group address. */ + ip4_address_t group_address; ip4_address_t src_addresses[0]; } igmp_membership_group_v3_t; +always_inline u32 +igmp_membership_group_v3_length (const igmp_membership_group_v3_t * g) +{ + return (sizeof (*g) + + (sizeof (ip4_address_t) * + clib_net_to_host_u16 (g->n_src_addresses))); +} + always_inline igmp_membership_group_v3_t * igmp_membership_group_v3_next (igmp_membership_group_v3_t * g) { @@ -153,6 +189,24 @@ typedef struct igmp_membership_group_v3_t groups[0]; } igmp_membership_report_v3_t; +always_inline u32 +igmp_membership_report_v3_length (const igmp_membership_report_v3_t * r) +{ + const igmp_membership_group_v3_t *g; + u32 len, ii, glen; + + len = sizeof (igmp_membership_report_v3_t); + g = r->groups; + + for (ii = 0; ii < clib_net_to_host_u16 (r->n_groups); ii++) + { + glen = igmp_membership_group_v3_length (g); + g = (const igmp_membership_group_v3_t *) (((u8 *) g) + glen); + len += glen; + } + return (len); +} + /* IP6 flavor of IGMP is called MLD which is embedded in ICMP6. */ typedef struct {