X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Figmp_packet.h;h=cd4a40d77ff8a2cb99c3404a309fb0ce897704a3;hb=7c03ed4;hp=503259ece7c49219a78c51960f7859fb8c5093b8;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/ip/igmp_packet.h b/src/vnet/ip/igmp_packet.h index 503259ece7c..cd4a40d77ff 100644 --- a/src/vnet/ip/igmp_packet.h +++ b/src/vnet/ip/igmp_packet.h @@ -63,31 +63,77 @@ 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; +/** + * 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) +{ + f64 qqi; + + 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 { - /* membership_query, version <= 2 reports. */ + /* type 0x11 (IGMPv3) */ igmp_header_t header; - /* Multicast destination address. */ - ip4_address_t dst; -} igmp_message_t; + ip4_address_t group_address; + + /* Reserved, Suppress Router-Side Processing flag and + Querier's Robustness Variable RRRRSQQQ. */ + u8 resv_s_qrv; + + /* Querier's Query Interval Code */ + u8 qqi_code; + + u16 n_src_addresses; + 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) @@ -96,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; @@ -108,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) { @@ -135,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 {