//
// $Copyright$
//
// $Id: tunnel.def,v 1.1.1.1 2000/10/31 22:39:24 sekiya Exp $

//
// OFFLINK_GLOBAL_ADDRESS               Off-Link host's Global Address
// TN_GLOBAL_ADDRESS                    TN's Global Address
//

// Prefix
#define OFFLINK_GLOBAL_UCAST_PRFX _GLOBAL9_UCAST_PRFX
#define OFFLINK1_GLOBAL_UCAST_PRFX _GLOBAL8_UCAST_PRFX
#define OFFLINK2_GLOBAL_UCAST_PRFX _GLOBAL7_UCAST_PRFX
#define OFFLINK3_GLOBAL_UCAST_PRFX _GLOBAL6_UCAST_PRFX
#define TN_LINK0_GLOBAL_UCAST_PRFX _GLOBAL0_UCAST_PRFX
#define NUT_LINK0_GLOBAL_UCAST_PRFX _GLOBAL0_UCAST_PRFX
#define TN_LINK1_GLOBAL_UCAST_PRFX _GLOBAL1_UCAST_PRFX
#define NUT_LINK1_GLOBAL_UCAST_PRFX _GLOBAL1_UCAST_PRFX
#define AUTOMATIC_UCAST_PRFX _GLOBAL1_UCAST_PRFX

// Prefix Length
#define GLOBAL_UCAST_PRFXLEN _GLOBAL0_UCAST_PRFXLEN
#define AUTOMATOC_UCAST_PRFXLEN _COMPATIBLE_UCAST_PRFXLEN

// IPv6 Address
#define OFFLINK_GLOBAL_ADDRESS v6(_GLOBAL9A0N_UCAST_ADDR)
#define OFFLINK_AUTOMATIC_ADDRESS v6(_COMPATIBLE7A1N_UCAST_ADDR)
#define OFFLINK1_GLOBAL_ADDRESS v6(_GLOBAL8A0N_UCAST_ADDR)
#define OFFLINK1_AUTOMATIC_ADDRESS v6(_COMPATIBLE6A1N_UCAST_ADDR)
#define OFFLINK2_GLOBAL_ADDRESS v6(_GLOBAL7A0N_UCAST_ADDR)
#define OFFLINK3_GLOBAL_ADDRESS v6(_GLOBAL6A0N_UCAST_ADDR)
#define TN_LINK0_GLOBAL_ADDRESS v6merge(TN_LINK0_GLOBAL_UCAST_PRFX, \
	GLOBAL_UCAST_PRFXLEN, \
	v6("::1"))
#define TN_LINK0_AUTOMATIC_ADDRESS v6(_COMPATIBLE0A1N_UCAST_ADDR)
#define NUT_LINK0_GLOBAL_ADDRESS v6merge( NUT_LINK0_GLOBAL_UCAST_PRFX, \
	GLOBAL_UCAST_PRFXLEN, \
	nutv6())
#define NUT_LINK0_AUTOMATIC_ADDRESS v6(_COMPATIBLE0A2N_UCAST_ADDR)
#define TN_LINK1_GLOBAL_ADDRESS v6merge(TN_LINK1_GLOBAL_UCAST_PRFX, \
	GLOBAL_UCAST_PRFXLEN, \
	v6("::1"))
#define TN_LINK1_AUTOMATIC_ADDRESS v6(_COMPATIBLE1A1N_UCAST_ADDR)
#define NUT_LINK1_GLOBAL_ADDRESS v6merge( NUT_LINK1_GLOBAL_UCAST_PRFX, \
	GLOBAL_UCAST_PRFXLEN, \
	nutv6("Link1"))
#define NUT_LINK1_AUTOMATIC_ADDRESS v6(_COMPATIBLE1A2N_UCAST_ADDR)
#define NUT_LINK1_GLOBAL_UNKNOWN_ADDRESS v6merge( NUT_LINK1_GLOBAL_UCAST_PRFX, \
	GLOBAL_UCAST_PRFXLEN, \
	v6("::1"))

#define TN_LINK0_ONEOF_ADDRESSES oneof(TN_LINK0_GLOBAL_ADDRESS,tnv6())
#define NUT_LINK0_ONEOF_ADDRESSES oneof(NUT_LINK0_GLOBAL_ADDRESS,nutv6())
#define TN_LINK1_ONEOF_ADDRESSES oneof(TN_LINK1_GLOBAL_ADDRESS,tnv6())
#define NUT_LINK1_ONEOF_ADDRESSES oneof(NUT_LINK1_GLOBAL_ADDRESS,nutv6())

// IPv4 Address

#define TN_LINK1_V4_ADDRESS	v4(_IPV41A1N_UCAST_ADDR)
#define NUT_LINK1_V4_ADDRESS v4(_IPV41A2N_UCAST_ADDR)
#define TN_LINK0_V4_ADDRESS	v4(_IPV40A1N_UCAST_ADDR)
#define NUT_LINK0_V4_ADDRESS v4(_IPV40A2N_UCAST_ADDR)
#define V4_UNSPECIFIED_ADDRESS v4("0.0.0.0")
#define V4_NOCONFIGURED_ADDRESS v4(_IPV49A4N_UCAST_ADDR)
#define V4_OFFLINK_ADDRESS v4(_IPV48A1N_UCAST_ADDR)
#define V4_OFFLINK0_ADDRESS v4(_IPV47A1N_UCAST_ADDR)
#define V4_OFFLINK1_ADDRESS v4(_IPV46A1N_UCAST_ADDR)

// Ethernet Address

#define UNSPEC_MAC_ADDR ether("00:00:00:00:00:00")

// define Packets
//

//
// Echo Request
// TN (link local address) --> NUT (link local address)
#define echo_request_tn2nut_ONLINK( \
        pNAME, \
        EchoRequest_data \
) \
FEM_icmp6_echo_request( \
         pNAME, \
         _HETHER_tn2nut, \
                { \
                _SRC(tnv6()); \
                _DST(nutv6()); \
         }, \
                 { \
                 payload=EchoRequest_data; \
         } \
)  

//
// Echo Request
// TN (global address) --> NUT (global address)
#define echo_request_tn2nut_GLOBALADDR_ONLINK( \
        pNAME, \
        EchoRequest_data \
) \
FEM_icmp6_echo_request( \
         pNAME, \
         _HETHER_tn2nut, \
                { \
                _SRC(TN_LINK0_GLOBAL_ADDRESS); \
                _DST(NUT_LINK0_GLOBAL_ADDRESS); \
         }, \
                 { \
                 payload=EchoRequest_data; \
         } \
)  

//
// Echo Request
// TN (link local address) <-- NUT (link local address)
#define echo_request_nut2tn_ONLINK( \
        pNAME, \
        EchoRequest_data \
) \
FEM_icmp6_echo_request( \
         pNAME, \
         _HETHER_nut2tn, \
                { \
                _SRC(nutv6()); \
                _DST(tnv6()); \
         }, \
                 { \
                 payload=EchoRequest_data; \
         } \
) 
 
//
// Echo Request
// TN (global address) <-- NUT (global address)
#define echo_request_nut2tn_GLOBALADDR_ONLINK( \
        pNAME, \
        EchoRequest_data \
) \
FEM_icmp6_echo_request( \
         pNAME, \
         _HETHER_nut2tn, \
                { \
                _SRC(NUT_LINK0_GLOBAL_ADDRESS); \
                _DST(TN_LINK0_GLOBAL_ADDRESS); \
         }, \
                 { \
                 payload=EchoRequest_data; \
         } \
)  

//
// Echo Reply 
// TN (link local address) <-- NUT (link local address)
#define echo_reply_nut2tn_ONLINK( \
        pNAME,\
        EchoReply_data \
) \
FEM_icmp6_echo_reply( \
        pNAME, \
        _HETHER_nut2tn, \
                { \
                _SRC(nutv6()); \
                _DST(tnv6()); \
        }, \
                { \
                payload=EchoReply_data; \
        } \
)

//
// Echo Reply 
// TN (global address) <-- NUT (global address)
#define echo_reply_nut2tn_GLOBALADDR_ONLINK( \
        pNAME,\
        EchoReply_data \
) \
FEM_icmp6_echo_reply( \
        pNAME, \
        _HETHER_nut2tn, \
                { \
                _SRC(NUT_LINK0_GLOBAL_ADDRESS); \
                _DST(TN_LINK0_GLOBAL_ADDRESS); \
        }, \
                { \
                payload=EchoReply_data; \
        } \
)

//
// Echo Reply 
// TN (link local address) --> NUT (link local address)
#define echo_reply_tn2nut_ONLINK( \
        pNAME,\
        EchoReply_data \
) \
FEM_icmp6_echo_reply( \
        pNAME, \
        _HETHER_tn2nut, \
                { \
                _SRC(tnv6()); \
                _DST(nutv6()); \
        }, \
                { \
                payload=EchoReply_data; \
        } \
)

//
// Echo Reply 
// TN (global address) --> NUT (global address)
#define echo_reply_tn2nut_GLOBALADDR_ONLINK( \
        pNAME,\
        EchoReply_data \
) \
FEM_icmp6_echo_reply( \
        pNAME, \
        _HETHER_tn2nut, \
                { \
                _SRC(TN_LINK0_GLOBAL_ADDRESS); \
                _DST(NUT_LINK0_GLOBAL_ADDRESS); \
        }, \
                { \
                payload=EchoReply_data; \
        } \
)

// 
// UDP
//

#define UDP_NAME(_pNAME) UDP_##_pNAME
#define HDR_UDP_NAME(_pNAME) HDR_UDP_##_pNAME

#define FEM_udp_exth(_pNAME,_pETHER,_oHDR_IPV6,_oPACKET_IPV6,oHDR_UDP,PAYLOAD_NAME) \
FEM_hdr_ipv6_exth(_pNAME,_pETHER,_oHDR_IPV6,_oPACKET_IPV6) \
Upp_UDP UDP_NAME(_pNAME) { \
        header=HDR_UDP_NAME(_pNAME); \
		payload=PAYLOAD_NAME; \
		} \
Hdr_UDP HDR_UDP_NAME(_pNAME) \
		oHDR_UDP

#define FEM_udp(_pNAME,_pETHER,_oHDR_IPV6,oHDR_UDP,PAYLOAD_NAME) \
FEM_udp_exth(_pNAME,_pETHER,_oHDR_IPV6, \
                { header=_HDR_IPV6_NAME(_pNAME); \
                  upper=UDP_NAME(_pNAME); }, \
                oHDR_UDP,PAYLOAD_NAME)


//
// Fragmented Echo Request Packet
//

#define _HDR_FRAGMENT_NAME(_pNAME) _FRAGMENT_##_pNAME 
#define _PAYLOAD_NAME(_pNAME) _PAYLOAD_##_pNAME 



#define FEM_fragment(_pNAME,_pETHER,_oHDR_IPV6, \
                                         _oHDR_FRAGMENT,_oPAYLOAD) \
FEM_hdr_ipv6_exth(_pNAME,_pETHER,_oHDR_IPV6, \
                { \
                header=_HDR_IPV6_NAME(_pNAME); \
                exthdr=_HDR_FRAGMENT_NAME(_pNAME); \
                upper=_PAYLOAD_NAME(_pNAME); \
        } \
) \
Hdr_Fragment _HDR_FRAGMENT_NAME(_pNAME) \
        _oHDR_FRAGMENT \
Payload _PAYLOAD_NAME(_pNAME) \
        _oPAYLOAD


#define FEM_fragment_tn2nut_LLA(_pNAME,_oHDR_FRAGMENT,_oPAYLOAD) \
FEM_fragment( \
         _pNAME, \
         _HETHER_tn2nut, \
                { \
                NextHeader=44; \
		         _SRC(tnv6()); \
                 _DST(nutv6()); \
         }, \
         _oHDR_FRAGMENT,\
         _oPAYLOAD \
)

#define FEM_fragment_tn2nut_source_LLA_destination_MA(_pNAME,_oHDR_FRAGMENT,_oPAYLOAD) \
FEM_fragment( \
         _pNAME, \
         _HETHER_tn2nut, \
                { \
                NextHeader=44; \
		         _SRC(tnv6()); \
                 _DST(v6(_ALLNODES_MCAST_ADDR)); \
         }, \
         _oHDR_FRAGMENT,\
         _oPAYLOAD \
)

#define FEM_fragment_tn2nut_GA(_pNAME,_oHDR_FRAGMENT,_oPAYLOAD) \
FEM_fragment( \
         _pNAME, \
         _HETHER_tn2nut, \
                { \
                NextHeader=44; \
		         _SRC(TN_LINK0_GLOBAL_ADDRESS); \
                 _DST(NUT_LINK0_GLOBAL_ADDRESS); \
         }, \
         _oHDR_FRAGMENT,\
         _oPAYLOAD \
)

// 
// IPv4 
//

//
// v6 over v4 packet
//
#define FEM_v6overv4_exth(_pNAME,_pETHER,_oHDR_IPV4,_oPACKET_IPV4,_oHDR_IPV6,_oPACKET_IPV6) \
FEM_hdr_ipv4_exth( \
	_pNAME, \
	_pETHER, \
	_oHDR_IPV4, \
	_oPACKET_IPV4 \
) \
Packet_IPv6 _PACKET_IPV6_NAME(_pNAME) \
        _oPACKET_IPV6 \
Hdr_IPv6 _HDR_IPV6_NAME(_pNAME) \
        _oHDR_IPV6


//
// v6 over v4 packet -- ipv4 no defined --
//
#define FEM_v6overv4_exth_ipv6_exth(_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oPACKET_IPV6) \
FEM_v6overv4_exth( \
	_pNAME, \
	_pETHER, \
	_oHDR_IPV4, \
		{ \
        header=_HDR_IPV4_NAME(_pNAME); \
        upper=_PACKET_IPV6_NAME(_pNAME); \
	}, \
	_oHDR_IPV6, \
	_oPACKET_IPV6) 

//
// v6 over v4 packet -- ipv4 defined --
//
#define FEM_v6overv4_ipv6_exth(_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oPACKET_IPV6) \
FEM_v6overv4_exth( \
	_pNAME, \
	_pETHER, \
		{ \
		Version=4; \
		IHL=5; \
		TypeOfService=0; \
		Protocol=41; \
		SourceAddress=V4_SRC_ADDR; \
		DestinationAddress=V4_DST_ADDR; \
	}, \
		{ \
        header=_HDR_IPV4_NAME(_pNAME); \
        upper=_PACKET_IPV6_NAME(_pNAME); \
	}, \
	_oHDR_IPV6, \
	_oPACKET_IPV6) 


//
// v6 over v4 packet -- core icmpv6 defined --
//
#define FEM_v6overv4_exth_icmp6_exth(_pType,_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oPACKET_IPV6,_oICMPV6) \
FEM_v6overv4_exth_ipv6_exth(_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oPACKET_IPV6) \
ICMPv6_##_pType _ICMPV6_NAME(_pNAME) \
        _oICMPV6

#define FEM_v6overv4_exth_icmp6(_pType,_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oICMPV6) \
FEM_v6overv4_exth_icmp6_exth(_pType,_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6, \
		{ \
		header=_HDR_IPV6_NAME(_pNAME); \
        upper=_ICMPV6_NAME(_pNAME); \
	 }, \
	_oICMPV6) \

#define FEM_v6overv4_icmp6_exth(_pType,_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oPACKET_IPV6,_oICMPV6) \
FEM_v6overv4_ipv6_exth(_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oPACKET_IPV6) \
ICMPv6_##_pType _ICMPV6_NAME(_pNAME) \
        _oICMPV6

#define FEM_v6overv4_icmp6(_pType,_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oICMPV6) \
FEM_v6overv4_icmp6_exth(_pType,_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6, \
		{ \
		header=_HDR_IPV6_NAME(_pNAME); \
        upper=_ICMPV6_NAME(_pNAME); \
	 }, \
	_oICMPV6) \


//
// v6 over v4 packet -- icmpv6 echo request defined --
//
#define FEM_v6overv4_exth_icmp6_echo_request(_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oICMPV6_EchoRequest) \
FEM_v6overv4_exth_icmp6(EchoRequest,_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oICMPV6_EchoRequest) \

#define FEM_v6overv4_icmp6_echo_request(_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oICMPV6_EchoRequest) \
FEM_v6overv4_icmp6(EchoRequest,_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oICMPV6_EchoRequest) \

//
// v6 over v4 packet -- icmpv6 echo reply defined --
//
#define FEM_v6overv4_exth_icmp6_echo_reply(_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oICMPV6_EchoReply) \
FEM_v6overv4_exth_icmp6(EchoReply,_pNAME,_pETHER,_oHDR_IPV4,_oHDR_IPV6,_oICMPV6_EchoReply) \

#define FEM_v6overv4_icmp6_echo_reply(_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oICMPV6_EchoReply) \
FEM_v6overv4_icmp6(EchoReply,_pNAME,_pETHER,V4_SRC_ADDR,V4_DST_ADDR,_oHDR_IPV6,_oICMPV6_EchoReply) \



//
// Packets
//

_HETHER_define(HETHER_nut2tn_oneof,  nutether(), oneof(tnether(),_ETHER_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),_ETHER_SOLNODE_MCAST(tnv6())))

//
// Echo Request
//

echo_request_tn2nut_ONLINK(echo_request_tn2nut_LLA,ping_data)
 
echo_request_tn2nut_GLOBALADDR_ONLINK(echo_request_tn2nut_GA,ping_data) 

echo_request_tn2nut_GLOBALADDR_ONLINK(echo_request_tn2nut_GA_size_1500,data_size_1452) 

echo_request_tn2nut_ONLINK(echo_request_tn2nut_LLA_size_1500,data_size_1452) 

FEM_icmp6_echo_request( 
         echo_request_tn2nut_MA, 
         _HETHER_tn2allnodes, 
                { 
                _SRC(tnv6()); 
                _DST(v6(_ALLNODES_MCAST_ADDR)); 
         }, 
                 {
                 payload=ping_data; 
         } 
)  

FEM_icmp6_echo_request( 
         echo_request_tn2nut_OFFLINKA,
         _HETHER_tn2nut,
                { 
                _SRC(TN_LINK0_GLOBAL_ADDRESS); 
                _DST(OFFLINK_GLOBAL_ADDRESS); 
         }, 
                 {
                 payload=ping_data; 
         } 
)  

//
// Echo Reply
//

echo_reply_nut2tn_ONLINK(echo_reply_nut2tn_LLA,ping_data)

echo_reply_nut2tn_GLOBALADDR_ONLINK(echo_reply_nut2tn_GA,ping_data)

FEM_icmp6_echo_reply( 
        echo_reply_nut2tn_source_LLA_GA_destination_LLA, 
        _HETHER_nut2tn, 
                { 
                _SRC(oneof(nutv6(),NUT_LINK0_GLOBAL_ADDRESS)); 
                _DST(tnv6()); 
        }, 
                { 
                payload=ping_data; 
        } 
)

FEM_icmp6_echo_reply( 
        echo_reply_nut2tn_source_LLA_GA_destination_LLA_GA, 
        _HETHER_nut2tn, 
                { 
                _SRC(NUT_LINK0_ONEOF_ADDRESSES);
                _DST(TN_LINK0_ONEOF_ADDRESSES);
        }, 
                { 
                payload=ping_data; 
        } 
)

//
// payload  data
//
Payload ping_data
        {
        data=repeat(0xff,6);
    }

Payload data_size_1472
        {
        data=repeat(0xff,1472);
	}

Payload data_size_1422
        {
        data=repeat(0xff,1422);
	}

Payload data_size_1452
        {
        data=repeat(0xff,1452);
	}

Payload data_size_1432
        {
        data=repeat(0xff,1432);
	}

Payload data_size_1353
        {
        data=repeat(0xff,1353);
	}

Payload data_size_1352
        {
        data=repeat(0xff,1352);
	}

Payload data_size_1233
        {
        data=repeat(0xff,1233);
	}

Payload data_size_1232
        {
        data=repeat(0xff,1232);
	}

Payload data_size_1280 {
	data = repeat(0xaabbccdd,1280);
}

Payload data_size_952
        {
        data=repeat(0xff,952);
	}

Payload data_size_0 {
	data = {};
}

//
// Neighber Solicitasion Messages
//

//
// Neighber Solicitasion
// TN  <-- NUT (link local address)
// TargetAddress: TN's link local address
// Option : Source link layer address

FEM_icmp6_ns (
        ns_nut2tn_sourceLLA_targetLLA_optionSLL,
        HETHER_nut2tn_oneof,
                {
                _SRC(nutv6());
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=tnv6();
                option=_SLLOPT_nut;
        }
)

//
// Neighber Solicitasion
// TN  <-- NUT (link local address)
// TargetAddress: TN's link local address
// Option : none

FEM_icmp6_ns (
        ns_nut2tn_sourceLLA_targetLLA_nooption,
        HETHER_nut2tn_oneof,
                {
                _SRC(nutv6());
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=tnv6();
        }
)

//
// Neighber Solicitasion
// TN  <-- NUT (global address)
// TargetAddress: TN's link local address
// Option : Source link layer address

FEM_icmp6_ns (
        ns_nut2tn_sourceGA_targetLLA_optionSLL,
        HETHER_nut2tn_oneof,
                {
                _SRC(NUT_LINK0_GLOBAL_ADDRESS);
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=tnv6();
                option=_SLLOPT_nut;
        }
)

//
// Neighber Solicitasion
// TN  <-- NUT (global address)
// TargetAddress: TN's link local address
// Option : none

FEM_icmp6_ns (
        ns_nut2tn_sourceGA_targetLLA_nooption,
        HETHER_nut2tn_oneof,
                {
                _SRC(NUT_LINK0_GLOBAL_ADDRESS);
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=tnv6();
        }
)

//
// Neighber Solicitasion
// TN  <-- NUT (link local address)
// TargetAddress: TN's global address
// Option : Source link layer address

FEM_icmp6_ns (
        ns_nut2tn_sourceLLA_targetGA_optionSLL,
        HETHER_nut2tn_oneof,
                {
                _SRC(nutv6());
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=TN_LINK0_GLOBAL_ADDRESS;
                option=_SLLOPT_nut;
        }
)

//
// Neighber Solicitasion
// TN  <-- NUT (link local address)
// TargetAddress: TN's global address
// Option : none

FEM_icmp6_ns (
        ns_nut2tn_sourceLLA_targetGA_nooption,
        HETHER_nut2tn_oneof,
                {
                _SRC(nutv6());
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=TN_LINK0_GLOBAL_ADDRESS;
        }
)

//
// Neighber Solicitasion
// TN  <-- NUT (global address)
// TargetAddress: TN's global address
// Option : Source link layer address

FEM_icmp6_ns (
        ns_nut2tn_sourceGA_targetGA_optionSLL,
        HETHER_nut2tn_oneof,
                {
                _SRC(NUT_LINK0_GLOBAL_ADDRESS);
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=TN_LINK0_GLOBAL_ADDRESS;
                option=_SLLOPT_nut;
        }
)

//
// Neighber Solicitasion
// TN  <-- NUT (global address)
// TargetAddress: TN's global address
// Option : none

FEM_icmp6_ns (
        ns_nut2tn_sourceGA_targetGA_nooption,
        HETHER_nut2tn_oneof,
                {
                _SRC(NUT_LINK0_GLOBAL_ADDRESS);
                _DST(oneof(_IPV6_SOLNODE_MCAST(tnv6()),_IPV6_SOLNODE_MCAST(TN_LINK0_GLOBAL_ADDRESS),tnv6(),TN_LINK0_GLOBAL_ADDRESS));
                HopLimit=255;
        },
                {
                TargetAddress=TN_LINK0_GLOBAL_ADDRESS;
        }
)


//
// Neighber Advertisement Messages
//

//
// Neighber Advertisement 
// TN  (link local address)--> NUT (link local address)
// TargetAddress: TN's link local address

FEM_icmp6_na (
        na_tn2nut_sourceLLA_destinationLLA_targetLLA,
        _HETHER_tn2nut,
                {
                _SRC(tnv6());
                _DST(nutv6());
                HopLimit=255;
        },
                {
				RFlag=1;
                SFlag=1;
                OFlag=1;
                TargetAddress=tnv6();
                option=_TLLOPT_tn;
        }
)

//
// Neighber Advertisement 
// TN  (global address)--> NUT (global address)
// TargetAddress: TN's link local address

FEM_icmp6_na (
        na_tn2nut_sourceGA_destinationGA_targetLLA,
        _HETHER_tn2nut,
                {
                _SRC(TN_LINK0_GLOBAL_ADDRESS);
                _DST(NUT_LINK0_GLOBAL_ADDRESS);
                HopLimit=255;
        },
                {
				RFlag=1;
                SFlag=1;
                OFlag=1;
                TargetAddress=tnv6();
                option=_TLLOPT_tn;
        }
)

//
// Neighber Advertisement 
// TN  (link local address)--> NUT (link local address)
// TargetAddress: TN's global address

FEM_icmp6_na (
        na_tn2nut_sourceLLA_destinationLLA_targetGA,
        _HETHER_tn2nut,
                {
                _SRC(tnv6());
                _DST(nutv6());
                HopLimit=255;
        },
                {
				RFlag=1;
                SFlag=1;
                OFlag=1;
                TargetAddress=TN_LINK0_GLOBAL_ADDRESS;
                option=_TLLOPT_tn;
        }
)
//
// Neighber Advertisement 
// TN  (global address)--> NUT (global address)
// TargetAddress: TN's global address

FEM_icmp6_na (
        na_tn2nut_sourceGA_destinationGA_targetGA,
        _HETHER_tn2nut,
                {
                _SRC(TN_LINK0_GLOBAL_ADDRESS);
                _DST(NUT_LINK0_GLOBAL_ADDRESS);
                HopLimit=255;
        },
                {
				RFlag=1;
                SFlag=1;
                OFlag=1;
                TargetAddress=TN_LINK0_GLOBAL_ADDRESS;
                option=_TLLOPT_tn;
        }
)


//
// Router Advertisement 
// TN  (link local ddress)--> NUT (all node multicast  address)
FEM_icmp6_ra (
        ra,
        _HETHER_tn2allnodes,
                {
                _SRC(tnv6());
                _DST(v6(_LLOCAL_ALLNODES_MCAST_ADDR));
                HopLimit=255;
        },
                {
                CurHopLimit=254;
                LifeTime=3600;
                ReachableTime=0;
                RetransTimer=1005;
                option=_SLLOPT_tn;
                option=prefix_ra;
        }
)

Opt_ICMPv6_Prefix prefix_ra { 
        LFlag=1;
        AFlag=1;
        ValidLifetime=3600005;
        PreferredLifetime=3600005;
        Prefix=v6(NUT_LINK0_GLOBAL_UCAST_PRFX);
}

//
// ARP
//

//
// ARP Request Packet
// TN (Link1) --> NUT (Link1)
FEM_hdr_arp(
    arp_LINK1_tn2nut_request,
    _HETHER_tn2broadcast,
        {
        Operation=1;
        SenderHAddr=tnether();
        SenderPAddr=TN_LINK1_V4_ADDRESS;
        TargetHAddr=any;
        TargetPAddr=NUT_LINK1_V4_ADDRESS;
    }
)

//
// ARP Request Packet
// TN (Link0) --> NUT (Link0)
FEM_hdr_arp(
    arp_LINK0_tn2nut_request,
    _HETHER_tn2broadcast,
        {
        Operation=5;
        SenderHAddr=tnether();
        SenderPAddr=TN_LINK0_V4_ADDRESS;
        TargetHAddr=any;
        TargetPAddr=NUT_LINK0_V4_ADDRESS;
    }
)

//
//
// ARP Request Packet
// TN (Link1) <-- NUT (Link1)
FEM_hdr_arp(
    arp_LINK1_nut2tn_request,
    _HETHER_nut2broadcast,
        {
        Operation=1;
        SenderHAddr=nutether();
        SenderPAddr=NUT_LINK1_V4_ADDRESS;
        TargetHAddr=any;
        TargetPAddr=TN_LINK1_V4_ADDRESS;
    }
)

// ARP Request Packet
// TN (Link0) <-- NUT (Link0)
FEM_hdr_arp(
    arp_LINK0_nut2tn_request,
    _HETHER_nut2broadcast,
        {
        Operation=1;
        SenderHAddr=nutether();
        SenderPAddr=NUT_LINK0_V4_ADDRESS;
        TargetHAddr=any;
        TargetPAddr=TN_LINK0_V4_ADDRESS;
    }
)

//
// ARP Reply Packet
// TN (Link1) --> NUT (Link1)
FEM_hdr_arp(
    arp_LINK1_tn2nut_reply,
    _HETHER_tn2nut,
        {
        Operation=2;
        SenderHAddr=tnether();
        SenderPAddr=TN_LINK1_V4_ADDRESS;
        TargetHAddr=nutether();
        TargetPAddr=NUT_LINK1_V4_ADDRESS;
    }
)

//
// ARP Reply Packet
// TN (Link0) --> NUT (Link0)
FEM_hdr_arp(
    arp_LINK0_tn2nut_reply,
    _HETHER_tn2nut,
        {
        Operation=2;
        SenderHAddr=tnether();
        SenderPAddr=TN_LINK0_V4_ADDRESS;
        TargetHAddr=nutether();
        TargetPAddr=NUT_LINK0_V4_ADDRESS;
    }
)

//
// ARP Reply Packet
// TN (Link1) <-- NUT (Link1)
FEM_hdr_arp(
    arp_LINK1_nut2tn_reply,
    _HETHER_nut2tn,
        {
        Operation=2;
        SenderHAddr=nutether();
        SenderPAddr=NUT_LINK1_V4_ADDRESS;
        TargetHAddr=tnether();
        TargetPAddr=TN_LINK1_V4_ADDRESS;
    }
)

//
// ARP Reply Packet
// TN (Link0) <-- NUT (Link0)
FEM_hdr_arp(
    arp_LINK0_nut2tn_reply,
    _HETHER_nut2tn,
        {
        Operation=2;
        SenderHAddr=nutether();
        SenderPAddr=NUT_LINK0_V4_ADDRESS;
        TargetHAddr=tnether();
        TargetPAddr=TN_LINK0_V4_ADDRESS;
    }
)

//
// IPv4
//

//
// IPv4 Echo Request
// TN (Link1) --> NUT (Link1)
FEM_icmp4_echo_request(
	echo_request_LINK1_v4_tn2nut,
	_HETHER_tn2nut,
		{
		SourceAddress=TN_LINK1_V4_ADDRESS;
		DestinationAddress=NUT_LINK1_V4_ADDRESS;	
	},
		{
		payload=ping_data;
	}
)

//
// IPv4 Echo Request
// TN (Link0) --> NUT (Link0)
FEM_icmp4_echo_request(
	echo_request_LINK0_v4_tn2nut,
	_HETHER_tn2nut,
		{
		SourceAddress=TN_LINK0_V4_ADDRESS;
		DestinationAddress=NUT_LINK0_V4_ADDRESS;	
	},
		{
		payload=ping_data;
	}
)

//
// IPv4 Echo Reply
// TN (Link1) <-- NUT (Link1)
FEM_icmp4_echo_reply (
	echo_reply_LINK1_v4_nut2tn,
	_HETHER_nut2tn,
		{
		SourceAddress=NUT_LINK1_V4_ADDRESS;
		DestinationAddress=TN_LINK1_V4_ADDRESS;	
	},
		{
		payload=ping_data;
	}
)

//
// IPv4 Echo Reply
// TN (Link0) <-- NUT (Link0)
FEM_icmp4_echo_reply (
	echo_reply_LINK0_v4_nut2tn,
	_HETHER_nut2tn,
		{
		SourceAddress=NUT_LINK0_V4_ADDRESS;
		DestinationAddress=TN_LINK0_V4_ADDRESS;	
	},
		{
		payload=ping_data;
	}
)
