/* uni3x - UNI 3.0 and 3.1 message format decription */

/* Written 1995,1996 by Werner Almesberger, EPFL-LRC */

/*
 * Fields only available in UNI 3.0 are marked with "UNI 3.0 only" (without the
 * double quotes). Don't assign a value when generating UNI 3.1 messages.
 */

#undef linux /* grr ... */

include "atmsap.h"
include "q2931.h"


#define VAR_STD_HDR(name,defl) \
    _ext <1@8,more> = 1 \
    name##_cs "q2931_cs" <2@6,more> = defl \
    _flag "atm_flag" <1@5,more> = ATM_FLAG_NO \
    _action_ind "atm_ai_ie" <3@1> = 0 /* only 2 bits in UNI 3.0 */ \
    _ie_len <16> = recover RECOV_IND_IE length

#define ITU_STD_HDR VAR_STD_HDR(,Q2931_CS_ITU)
#define NET_STD_HDR VAR_STD_HDR(,Q2931_CS_NET)


def ie_aal = {
    ITU_STD_HDR {
	aal_type <8> = case {
	    5 {
		_id "atm_aalp" <8> = multi {
		    ATM_AALP_FW_MAX_SDU {
			fw_max_sdu <16>
		    }
		    ATM_AALP_BW_MAX_SDU {
			bw_max_sdu <16>
		    }
#if defined(UNI30) || defined(ALLOW_UNI30)
		    ATM_AALP_AAL_MODE {
			aal_mode <8> # UNI 3.0 only
		    }
#endif
		    ATM_AALP_SSCS {
			sscs_type <8>
		    }
		}
	    }
	}
    }
}


def ie_td = { # UNI 3.0 calls this "User Cell Rate"
    ITU_STD_HDR {
	_id "atm_td" <8> = multi {
	    ATM_TD_FW_PCR_0 {
		fw_pcr_0 <24>
	    }
	    ATM_TD_BW_PCR_0 {
		bw_pcr_0 <24>
	    }
	    ATM_TD_FW_PCR_01 {
		fw_pcr_01 <24>
	    }
	    ATM_TD_BW_PCR_01 {
		bw_pcr_01 <24>
	    }
	    ATM_TD_FW_SCR_0 {
		fw_scr_0 <24>
	    }
	    ATM_TD_BW_SCR_0 {
		bw_scr_0 <24>
	    }
	    ATM_TD_FW_SCR_01 {
		fw_scr_01 <24>
	    }
	    ATM_TD_BW_SCR_01 {
		bw_scr_01 <24>
	    }
	    ATM_TD_FW_MBS_0 {
		fw_mbs_0 <24>
	    }
	    ATM_TD_BW_MBS_0 {
		bw_mbs_0 <24>
	    }
	    ATM_TD_FW_MBS_01 {
		fw_mbs_01 <24>
	    }
	    ATM_TD_BW_MBS_01 {
		bw_mbs_01 <24>
	    }
	    ATM_TD_BEST_EFFORT {
		best_effort <0>
	    }
	    ATM_TD_TM_OPT {
		bw_tag "atm_tag" <1@2,more>
		fw_tag "atm_tag" <1@1>
	    }
	}
    }
}


def ie_bbcap = {
    ITU_STD_HDR {
	bearer_class "atm_bc" <5@1,more>
	_ext <1@8> = case {
	    0 {
		_ext <1@8,more> = 1
		traf_type "atm_tt" <3@3,more> = ATM_TT_NO_IND
		tim_req "atm_tr" <2@1> = ATM_TR_NO_IND
	    }
	    default 1 {}
	}
	_ext <1@8,more> = 1
	susc_clip "atm_stc" <2@6,more> = ATM_STC_NO
	upcc "atm_upcc" <2@1> = ATM_UPCC_P2P
    }
}


def ie_bhli = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
	hli_type <7@1> = case {
# Note: cannot use ATM_HL_* here, because those values are incremented by one
	    0 { # ISO
		iso_hli <-64>
	    }
	    1 { # User Specific
		user_hli <-64>
	    }
	    2 { # High layer profile - UNI 3.0 only
		hlp <32>
	    }
	    3 { # Vendor-Specific Application identifier
		hli_oui <24>
		app_id <32>
	    }
	}
    }
}


def ie_blli = {
    ITU_STD_HDR {
	_lid <2@6,more> = multi {
	    1 { # not supported in UNI 3.0 or 3.1
		_ext <1@8,more> = 1
		uil1_proto <5@1>
	    }
	    2 {
		uil2_proto "atm_l2" <5@1,more> = case {
		    ATM_L2_X25_LL,ATM_L2_X25_ML,ATM_L2_HDLC_ARM,
		      ATM_L2_HDLC_NRM,ATM_L2_HDLC_ABM,ATM_L2_Q922,
		      ATM_L2_ISO7776 { # CCITT encoding
			_ext <1@8> = case {
			    0 {
				l2_mode "atm_imd" <2@6,more> = ATM_IMD_NORMAL
				q933 <2@1,more> = 0
				_ext <1@8> = case {
				    0 {
					window_size <7@1,more>
					_ext <1@8> = 1
				    }
				    default 1 {}
				}
			    }
			    default 1 {}
			}
		    }
		    ATM_L2_USER { # User specified
			_ext <1@8> = 0
			user_l2 <7@1>
		    }
		    default ATM_L2_ISO1745,ATM_L2_Q291,ATM_L2_LAPB,
		      ATM_L2_ISO8802,ATM_L2_X75 { # No additional data
			_ext <1@8> = 1
		    }
		}
	    }
	    3 {
		uil3_proto "atm_l3" <5@1,more> = case {
		    ATM_L3_X25,ATM_L3_ISO8208,ATM_L3_X223 { # CCITT coding
			_ext <1@8> = case {
			    0 {
				l3_mode "atm_imd" <2@6,more> = ATM_IMD_NORMAL
				_ext <1@8> = case {
				    0 {
					def_pck_size <4@1>
					_ext <1@8> = case {
					    0 {
						_ext <1@8> = 1
						pck_win_size <7@1>
					    }
					    default 1 {}
					}
				    }
				    default 1 {}
				}
			    }
			    default 1 {}
			}
		    }
		    ATM_L3_TR9577 { # ISO/IEC TR9577
			_ext <1@8> = case {
			    0 {
				_ext <1@8,more> = 0
				ipi_high <7@1> = case {
				    0x40 { # SNAP hack
					_ext <1@8,more> = 1
					_ipi_low <1@7> = case { # ugly
					    0 {
						_ext <1@8,more> = 1
						_snap_id <2@6> = 0
						oui <24>
						pid <16>
					    }
					    default 1 {}
					}
				    }
				    default 0x0 { # ugly
					_ext <1@8,more> = 1
					ipi_low <1@7>
				    }
				}
			    }
			    default 1 {}
			}
		    }
		    ATM_L3_USER { # User specified
			_ext <1@8> = 0
			user_l3 <7@1>
		    }
		}
	    }
	}
    }
}


def ie_call_state = {
    ITU_STD_HDR {
	call_state <6@1>
    }
}


def ie_cdpn = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
	_plan "atm_np" <4@1,more> = case {
	    ATM_NP_E164 {
		_type "atm_ton" <3@5> = ATM_TON_INTRNTNL
		cdpn_e164 <-96>
	    }
	    ATM_NP_NSAP { # ATM Endsystem Address
		_type "atm_ton" <3@5> = ATM_TON_UNKNOWN
		cdpn_esa <-160>
	    }
	}
    }
}


def ie_cdps = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
#ifdef UNI30
	_type "atm_sat" <3@5,more> = ATM_SAT_NSAP
#endif
#ifdef UNI31
	cdps_type "atm_sat" <3@5,more> = ATM_SAT_NSAP
#endif
	_oddeven <1@4> = 0
	cdps <-160>
    }
}


def ie_cgpn = { # @@@ extend language to allow same trick as for cdpn
    ITU_STD_HDR {
	cgpn_plan "atm_np" <4@1,more>
	cgpn_type "atm_ton" <3@5,more>
	_ext <1@8> = case {
	    0 {
		_ext <1@8,more> = 1
		pres_ind "atm_prs" <2@6,more> = ATM_PRS_ALLOW
		scr_ind "atm_scrn" <2@1> = ATM_SCRN_UP_NS
	    }
	    default 1 {}
	}
	cgpn <-160>
    }
}


def ie_cgps = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
#ifdef UNI30
	_type "atm_sat" <3@5,more> = ATM_SAT_NSAP
#endif
#ifdef UNI31
	cgps_type "atm_sat" <3@5,more> = ATM_SAT_NSAP
#endif
	_oddeven <1@4> = 0
	cgps <-160>
    }
}


def ie_cause = {
    VAR_STD_HDR(cause,Q2931_CS_ITU) {
	_ext <1@8,more> = 1
	location "atm_loc" <4@1> = ATM_LOC_USER
	_ext <1@8,more> = 1
	cause "atm_cv" <7@1> = case {
	    ATM_CV_UNALLOC,ATM_CV_NO_ROUTE_DEST,ATM_CV_QOS_UNAVAIL { # Note 2
		break
		_ext <1@8,more> = 1
		pu "atm_pu" <1@4,more> = ATM_PU_USER
		na "atm_na" <1@3,more> = ATM_NA_NORMAL
		cond2 "atm_cond" <2@1> = ATM_COND_UNKNOWN
	    }
	    ATM_CV_CALL_REJ { # Note 3
		break
		_ext <1@8,more> = 1
		cond3 "atm_cond" <2@1,more> = ATM_COND_UNKNOWN
		reason <5@3> = case {
		    ATM_RSN_USER {
			user_diag <-216>
		    }
		    ATM_RSN_IE_MISS,ATM_RSN_IE_INSUFF {
			ie_id3 "atm_ie" <8>
		    }
		}
	    }
	    ATM_CV_NUM_CHANGED { # Note 4
		break
		new_dest <-224> # good luck ...
	    }
	    ATM_CV_REJ_CLIR { # Note 5
		break
		invalid <8> # not supported
	    }
	    ATM_CV_CI_ACC_INF_DISC,ATM_CV_INCOMP_DEST,ATM_CV_MAND_IE_MISSING,
	      ATM_CV_UNKNOWN_IE,ATM_CV_INVALID_IE { # Note 6
		break
		ie_id6 <-224>
	    }
	    ATM_CV_UCR_UNAVAIL { # Note 8
		break
		ucr_id <-224>
	    }
	    ATM_CV_NO_SUCH_CHAN { # Note 9
		break
		unav_vpci <16>
		unav_vci <16>
	    }
	    ATM_CV_UNKNOWN_MSG_TYPE,ATM_CV_INCOMP_MSG { # Note 10
		break
		bad_msg_type "qmsg" <8>
	    }
	    ATM_CV_TIMER_EXP { # Note 11
		break
		timer <24>
	    }
	    default 0 {}
	}
    }
}


def ie_conn_id = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
	_vp_ass "atm_vpa" <2@4,more> = 1 /* explicit */
	_pref_exc "atm_poe" <3@1> = 0
	vpi <16>
	vci <16>
    }
}


def ie_qos = {
#ifdef UNI30
    NET_STD_HDR {
#else
    /*
     * Depending on what values are put into qos_fw and qos_bw, this may
     * still be invalid. But at least the defaults should be okay. Note
     * that defining UNI30 and UNI31 together yields only the UNI30
     * behaviour. We assume that everybody who implements UNI 3.1 today
     * has a similar kludge in their networking code, so we should get
     * away with that.
     */
    VAR_STD_HDR(qos,Q2931_CS_NET) {
#endif
	qos_fw <8> = 0
	qos_bw <8> = 0
    }
}


def ie_bbrep = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
	rep_ind <4@1> = 2
    }
}


def ie_restart = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
	rst_class <3@1>
    }
}


def ie_bbs_comp = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
	bbsc_ind <7@1> = 0x21
    }
}


def ie_tns = {
    ITU_STD_HDR {
	_ext <1@8,more> = 1
	_net_type <3@5,more> = 2
	_carrier_id <4@1> = 1
	net_id <-32># how many actually ?
    }
}


def ie_ep_ref = {
    ITU_STD_HDR {
	_ep_type <8> = 0
	ep_ref <16>
    }
}


def ie_ep_state = {
    ITU_STD_HDR {
	ep_state <6@1>
    }
}


{
    _pdsc "q2931_proto" <8> = Q2931_PROTO_DSC
    _cr_len <8> = 3
    call_ref <24>
    msg_type "qmsg" <8>
    _ext <1@8,more> = 1
    _flag "atm_flag" <1@5,more> = ATM_FLAG_NO
    _action_ind "atm_ai_msg" <2@1> = 0
    msg_len <16> = length {
	_ie_id "atm_ie" <8> = multi {
	    aal:	ATM_IE_AAL		ie_aal
	    td:		ATM_IE_TD		ie_td
	    bbcap:	ATM_IE_BBCAP		ie_bbcap
	    bhli:	ATM_IE_BHLI		ie_bhli
	    blli:	ATM_IE_BLLI		ie_blli
/*
	    blli2:	ATM_IE_BLLI		ie_blli
	    blli3:	ATM_IE_BLLI		ie_blli
*/
	    call_state:	ATM_IE_CALL_STATE	ie_call_state
	    cdpn:	ATM_IE_CDPN		ie_cdpn
	    cdps:	ATM_IE_CDPS		ie_cdps
	    cgpn:	ATM_IE_CGPN		ie_cgpn
	    cgps:	ATM_IE_CGPS		ie_cgps
	    cause:	ATM_IE_CAUSE		ie_cause
/*
	    cause2:	ATM_IE_CAUSE		ie_cause
*/
	    conn_id:	ATM_IE_CONN_ID		ie_conn_id
	    qos:	ATM_IE_QOS		ie_qos
	    bbrep:	ATM_IE_BBREP		ie_bbrep
	    restart:	ATM_IE_RESTART		ie_restart
	    bbs_comp:	ATM_IE_BBS_COMP		ie_bbs_comp
	    tns:	ATM_IE_TNS		ie_tns
	    ep_ref:	ATM_IE_EPR		ie_ep_ref
	    ep_state:	ATM_IE_EP_STATE		ie_ep_state
	    default 0 {
		VAR_STD_HDR(_,0)
		    abort RECOV_ASE_UNKNOWN_IE
	    }
	}
    }
}
