2011-11-08 17:36:12 +00:00
/* packet-vxlan.c
*
* Routines for Virtual eXtensible Local Area Network ( VXLAN ) packet dissection
2016-01-17 02:41:07 +00:00
* RFC 7348 plus draft - smith - vxlan - group - policy - 01
2011-11-08 17:36:12 +00:00
*
2016-07-02 19:34:37 +00:00
* ( c ) Copyright 2016 , Sumit Kumar Jha < sjha3 @ ncsu . edu >
* Support for VXLAN GPE ( https : //www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-02.txt)
*
2011-11-08 17:36:12 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2011-11-08 17:36:12 +00:00
*/
2012-09-20 02:03:38 +00:00
# include "config.h"
2011-11-08 17:36:12 +00:00
# include <epan/packet.h>
2015-07-07 08:46:34 +00:00
# include <epan/tfs.h>
2011-11-08 17:36:12 +00:00
2014-03-12 10:07:10 +00:00
# define UDP_PORT_VXLAN 4789
2016-07-02 19:34:37 +00:00
# define UDP_PORT_VXLAN_GPE 4790
# define VXLAN_IPV4 1
# define VXLAN_IPV6 2
# define VXLAN_ETHERNET 3
# define VXLAN_NSH 4
# define VXLAN_MPLS 5
2014-03-12 10:07:10 +00:00
2013-12-10 19:50:20 +00:00
void proto_register_vxlan ( void ) ;
void proto_reg_handoff_vxlan ( void ) ;
2011-11-08 17:36:12 +00:00
static int proto_vxlan = - 1 ;
static int hf_vxlan_flags = - 1 ;
2016-07-02 19:34:37 +00:00
static int hf_vxlan_gpe_flags = - 1 ;
2015-07-07 08:46:34 +00:00
static int hf_vxlan_flags_reserved = - 1 ;
2016-07-02 19:34:37 +00:00
static int hf_vxlan_reserved_8 = - 1 ;
2015-07-07 08:46:34 +00:00
static int hf_vxlan_flag_a = - 1 ;
static int hf_vxlan_flag_d = - 1 ;
2011-11-08 17:36:12 +00:00
static int hf_vxlan_flag_i = - 1 ;
2015-07-07 08:46:34 +00:00
static int hf_vxlan_flag_g = - 1 ;
static int hf_vxlan_gbp = - 1 ;
2011-11-08 17:36:12 +00:00
static int hf_vxlan_vni = - 1 ;
2016-07-02 19:34:37 +00:00
static int hf_vxlan_gpe_flag_i = - 1 ;
static int hf_vxlan_gpe_flag_p = - 1 ;
static int hf_vxlan_gpe_flag_o = - 1 ;
static int hf_vxlan_gpe_flag_ver = - 1 ;
static int hf_vxlan_gpe_flag_reserved = - 1 ;
static int hf_vxlan_gpe_reserved_16 = - 1 ;
static int hf_vxlan_next_proto = - 1 ;
2011-11-08 17:36:12 +00:00
static int ett_vxlan = - 1 ;
2016-07-02 19:34:37 +00:00
static int ett_vxlan_flags = - 1 ;
2011-11-08 17:36:12 +00:00
2015-07-07 08:46:34 +00:00
static const int * flags_fields [ ] = {
& hf_vxlan_flag_g ,
& hf_vxlan_flag_d ,
& hf_vxlan_flag_i ,
& hf_vxlan_flag_a ,
& hf_vxlan_flags_reserved ,
NULL
} ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
static const int * gpe_flags_fields [ ] = {
& hf_vxlan_gpe_flag_ver ,
& hf_vxlan_gpe_flag_i ,
& hf_vxlan_gpe_flag_p ,
& hf_vxlan_gpe_flag_o ,
& hf_vxlan_gpe_flag_reserved ,
NULL
} ;
static const value_string vxlan_next_protocols [ ] = {
{ VXLAN_IPV4 , " IPv4 " } ,
{ VXLAN_IPV6 , " IPv6 " } ,
{ VXLAN_ETHERNET , " Ethernet " } ,
{ VXLAN_NSH , " Network Service Header " } ,
{ VXLAN_MPLS , " MPLS " } ,
{ 0 , NULL }
} ;
2011-11-08 17:36:12 +00:00
static dissector_handle_t eth_handle ;
2016-07-02 19:34:37 +00:00
static dissector_handle_t ip_handle ;
static dissector_handle_t ipv6_handle ;
static dissector_handle_t nsh_handle ;
static dissector_handle_t mpls_handle ;
static dissector_table_t vxlan_dissector_table ;
2011-11-08 17:36:12 +00:00
2015-11-18 01:16:06 +00:00
static int
2016-07-02 19:34:37 +00:00
dissect_vxlan_common ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , int is_gpe )
2011-11-08 17:36:12 +00:00
{
2015-07-10 12:26:10 +00:00
proto_tree * vxlan_tree ;
proto_item * ti ;
2011-11-09 02:48:51 +00:00
tvbuff_t * next_tvb ;
int offset = 0 ;
2016-07-02 19:34:37 +00:00
int vxlan_next_proto = - 1 ;
2011-11-08 17:36:12 +00:00
2011-11-09 02:48:51 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " VxLAN " ) ;
col_clear ( pinfo - > cinfo , COL_INFO ) ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
ti = proto_tree_add_item ( tree , proto_vxlan , tvb , offset , 8 , ENC_NA ) ;
2011-11-09 02:48:51 +00:00
vxlan_tree = proto_item_add_subtree ( ti , ett_vxlan ) ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
if ( is_gpe ) {
proto_tree_add_bitmask ( vxlan_tree , tvb , offset , hf_vxlan_gpe_flags , ett_vxlan_flags , gpe_flags_fields , ENC_BIG_ENDIAN ) ;
offset + = 1 ;
proto_tree_add_item ( vxlan_tree , hf_vxlan_gpe_reserved_16 , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
proto_tree_add_item ( vxlan_tree , hf_vxlan_next_proto , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
vxlan_next_proto = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
} else {
proto_tree_add_bitmask ( vxlan_tree , tvb , offset , hf_vxlan_flags , ett_vxlan_flags , flags_fields , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
proto_tree_add_item ( vxlan_tree , hf_vxlan_gbp , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
}
2011-11-08 17:36:12 +00:00
2011-11-09 02:48:51 +00:00
proto_tree_add_item ( vxlan_tree , hf_vxlan_vni , tvb , offset , 3 , ENC_BIG_ENDIAN ) ;
2016-07-02 19:34:37 +00:00
offset + = 3 ;
2011-11-08 17:36:12 +00:00
2011-11-09 02:48:51 +00:00
proto_tree_add_item ( vxlan_tree , hf_vxlan_reserved_8 , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2016-07-02 19:34:37 +00:00
offset + = 1 ;
2011-11-09 02:48:51 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2016-07-02 19:34:37 +00:00
if ( is_gpe ) {
switch ( vxlan_next_proto ) {
case VXLAN_IPV4 :
call_dissector ( ip_handle , next_tvb , pinfo , tree ) ;
break ;
case VXLAN_IPV6 :
call_dissector ( ipv6_handle , next_tvb , pinfo , tree ) ;
break ;
case VXLAN_ETHERNET :
call_dissector ( eth_handle , next_tvb , pinfo , tree ) ;
break ;
case VXLAN_NSH :
if ( ! dissector_try_uint ( vxlan_dissector_table , VXLAN_NSH , next_tvb , pinfo , tree ) )
call_data_dissector ( next_tvb , pinfo , vxlan_tree ) ;
break ;
case VXLAN_MPLS :
call_dissector ( mpls_handle , next_tvb , pinfo , tree ) ;
break ;
default :
call_data_dissector ( next_tvb , pinfo , vxlan_tree ) ;
break ;
}
} else {
call_dissector ( eth_handle , next_tvb , pinfo , tree ) ;
}
2011-11-08 17:36:12 +00:00
2015-11-18 01:16:06 +00:00
return tvb_captured_length ( tvb ) ;
2011-11-08 17:36:12 +00:00
}
2016-07-02 19:34:37 +00:00
static int
dissect_vxlan_gpe ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
return dissect_vxlan_common ( tvb , pinfo , tree , TRUE ) ;
}
static int
dissect_vxlan ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
return dissect_vxlan_common ( tvb , pinfo , tree , FALSE ) ;
}
2011-11-08 17:36:12 +00:00
/* Register VxLAN with Wireshark */
void
proto_register_vxlan ( void )
{
2011-11-09 02:48:51 +00:00
static hf_register_info hf [ ] = {
{ & hf_vxlan_flags ,
{ " Flags " , " vxlan.flags " ,
2015-07-07 08:46:34 +00:00
FT_UINT16 , BASE_HEX , NULL , 0x00 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_flags ,
{ " Flags " , " vxlan.flags " ,
FT_UINT8 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flags_reserved ,
{ " Reserved(R) " , " vxlan.flags_reserved " ,
FT_BOOLEAN , 16 , NULL , 0x77b7 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_flag_reserved ,
{ " Reserved(R) " , " vxlan.flags_reserved " ,
FT_UINT8 , BASE_DEC , NULL , 0xC2 ,
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flag_g ,
{ " GBP Extension " , " vxlan.flag_g " ,
FT_BOOLEAN , 16 , TFS ( & tfs_defined_not_defined ) , 0x8000 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_flag_i ,
2015-07-07 08:46:34 +00:00
{ " VXLAN Network ID (VNI) " , " vxlan.flag_i " ,
FT_BOOLEAN , 16 , NULL , 0x0800 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flag_d ,
{ " Don't Learn " , " vxlan.flag_d " ,
FT_BOOLEAN , 16 , NULL , 0x0040 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flag_a ,
{ " Policy Applied " , " vxlan.flag_a " ,
FT_BOOLEAN , 16 , NULL , 0x0008 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_flag_ver ,
{ " Version " , " vxlan.ver " ,
FT_UINT8 , BASE_DEC , NULL , 0x30 ,
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_gpe_flag_i ,
{ " Instance " , " vxlan.i_bit " ,
FT_UINT8 , BASE_DEC , NULL , 0x08 ,
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_gpe_flag_p ,
{ " Next Protocol Bit " , " vxlan.p_bit " ,
FT_UINT8 , BASE_DEC , NULL , 0x04 ,
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_gpe_flag_o ,
{ " OAM bit " , " vxlan.o_bit " ,
FT_UINT8 , BASE_DEC , NULL , 0x01 ,
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_gbp ,
{ " Group Policy ID " , " vxlan.gbp " ,
FT_UINT16 , BASE_DEC , NULL , 0x00 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL
} ,
} ,
{ & hf_vxlan_vni ,
{ " VXLAN Network Identifier (VNI) " , " vxlan.vni " ,
FT_UINT24 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL
} ,
} ,
{ & hf_vxlan_reserved_8 ,
{ " Reserved " , " vxlan.reserved8 " ,
FT_UINT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_reserved_16 ,
{ " Reserved " , " vxlan.reserved_16 " ,
FT_UINT16 , BASE_DEC , NULL , 0x0000 ,
NULL , HFILL
} ,
} ,
{ & hf_vxlan_next_proto ,
{ " Next Protocol " , " vxlan.next_proto " ,
FT_UINT8 , BASE_DEC , VALS ( vxlan_next_protocols ) , 0x00 ,
NULL , HFILL
} ,
} ,
2011-11-09 02:48:51 +00:00
} ;
/* Setup protocol subtree array */
static gint * ett [ ] = {
& ett_vxlan ,
2016-07-02 19:34:37 +00:00
& ett_vxlan_flags ,
2011-11-09 02:48:51 +00:00
} ;
/* Register the protocol name and description */
proto_vxlan = proto_register_protocol ( " Virtual eXtensible Local Area Network " ,
" VXLAN " , " vxlan " ) ;
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array ( proto_vxlan , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2016-07-02 19:34:37 +00:00
vxlan_dissector_table = register_dissector_table ( " vxlan.next_proto " , " VXLAN Next Protocol " , proto_vxlan , FT_UINT8 , BASE_DEC , DISSECTOR_TABLE_ALLOW_DUPLICATE ) ;
2011-11-08 17:36:12 +00:00
}
void
proto_reg_handoff_vxlan ( void )
{
dissector_handle_t vxlan_handle ;
2016-07-02 19:34:37 +00:00
dissector_handle_t vxlan_gpe_handle ;
2011-11-08 17:36:12 +00:00
2016-01-17 02:41:07 +00:00
/*
* RFC 7348 Figures 1 and 2 , in the Payload section , say
*
* " (Note that the original Ethernet Frame's FCS is not included) "
*
* meaning that the inner Ethernet frame does * not * include an
* FCS .
*/
2016-03-16 13:02:52 +00:00
eth_handle = find_dissector_add_dependency ( " eth_withoutfcs " , proto_vxlan ) ;
2016-07-02 19:34:37 +00:00
ip_handle = find_dissector_add_dependency ( " ip " , proto_vxlan ) ;
ipv6_handle = find_dissector_add_dependency ( " ipv6 " , proto_vxlan ) ;
nsh_handle = find_dissector_add_dependency ( " nsh " , proto_vxlan ) ;
mpls_handle = find_dissector_add_dependency ( " mpls " , proto_vxlan ) ;
2011-11-08 17:36:12 +00:00
2015-12-09 03:49:44 +00:00
vxlan_handle = create_dissector_handle ( dissect_vxlan , proto_vxlan ) ;
2016-07-02 19:34:37 +00:00
vxlan_gpe_handle = create_dissector_handle ( dissect_vxlan_gpe , proto_vxlan ) ;
2014-03-12 10:07:10 +00:00
dissector_add_uint ( " udp.port " , UDP_PORT_VXLAN , vxlan_handle ) ;
2016-07-02 19:34:37 +00:00
dissector_add_uint ( " udp.port " , UDP_PORT_VXLAN_GPE , vxlan_gpe_handle ) ;
2014-06-20 16:43:28 +00:00
dissector_add_for_decode_as ( " udp.port " , vxlan_handle ) ;
2016-07-02 19:34:37 +00:00
dissector_add_for_decode_as ( " udp.port " , vxlan_gpe_handle ) ;
2014-03-12 10:07:10 +00:00
2011-11-08 17:36:12 +00:00
}
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/