Linux Audio

Check our new training course

Loading...
v6.13.7
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2#ifndef _CCID_H
  3#define _CCID_H
  4/*
  5 *  net/dccp/ccid.h
  6 *
  7 *  An implementation of the DCCP protocol
  8 *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  9 *
 10 *  CCID infrastructure
 11 */
 12
 13#include <net/sock.h>
 14#include <linux/compiler.h>
 15#include <linux/dccp.h>
 16#include <linux/list.h>
 17#include <linux/module.h>
 18
 19/* maximum value for a CCID (RFC 4340, 19.5) */
 20#define CCID_MAX		255
 21#define CCID_SLAB_NAME_LENGTH	32
 22
 23struct tcp_info;
 24
 25/**
 26 *  struct ccid_operations  -  Interface to Congestion-Control Infrastructure
 27 *
 28 *  @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.)
 29 *  @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled)
 30 *  @ccid_name: alphabetical identifier string for @ccid_id
 31 *  @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection
 32 *  @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket
 33 *
 34 *  @ccid_hc_{r,t}x_init: CCID-specific initialisation routine (before startup)
 35 *  @ccid_hc_{r,t}x_exit: CCID-specific cleanup routine (before destruction)
 36 *  @ccid_hc_rx_packet_recv: implements the HC-receiver side
 37 *  @ccid_hc_{r,t}x_parse_options: parsing routine for CCID/HC-specific options
 38 *  @ccid_hc_{r,t}x_insert_options: insert routine for CCID/HC-specific options
 39 *  @ccid_hc_tx_packet_recv: implements feedback processing for the HC-sender
 40 *  @ccid_hc_tx_send_packet: implements the sending part of the HC-sender
 41 *  @ccid_hc_tx_packet_sent: does accounting for packets in flight by HC-sender
 42 *  @ccid_hc_{r,t}x_get_info: INET_DIAG information for HC-receiver/sender
 43 *  @ccid_hc_{r,t}x_getsockopt: socket options specific to HC-receiver/sender
 44 */
 45struct ccid_operations {
 46	unsigned char		ccid_id;
 47	__u32			ccid_ccmps;
 48	const char		*ccid_name;
 49	struct kmem_cache	*ccid_hc_rx_slab,
 50				*ccid_hc_tx_slab;
 51	char			ccid_hc_rx_slab_name[CCID_SLAB_NAME_LENGTH];
 52	char			ccid_hc_tx_slab_name[CCID_SLAB_NAME_LENGTH];
 53	__u32			ccid_hc_rx_obj_size,
 54				ccid_hc_tx_obj_size;
 55	/* Interface Routines */
 56	int		(*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
 57	int		(*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
 58	void		(*ccid_hc_rx_exit)(struct sock *sk);
 59	void		(*ccid_hc_tx_exit)(struct sock *sk);
 60	void		(*ccid_hc_rx_packet_recv)(struct sock *sk,
 61						  struct sk_buff *skb);
 62	int		(*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
 63						    u8 opt, u8 *val, u8 len);
 64	int		(*ccid_hc_rx_insert_options)(struct sock *sk,
 65						     struct sk_buff *skb);
 66	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
 67						  struct sk_buff *skb);
 68	int		(*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
 69						    u8 opt, u8 *val, u8 len);
 70	int		(*ccid_hc_tx_send_packet)(struct sock *sk,
 71						  struct sk_buff *skb);
 72	void		(*ccid_hc_tx_packet_sent)(struct sock *sk,
 73						  unsigned int len);
 74	void		(*ccid_hc_rx_get_info)(struct sock *sk,
 75					       struct tcp_info *info);
 76	void		(*ccid_hc_tx_get_info)(struct sock *sk,
 77					       struct tcp_info *info);
 78	int		(*ccid_hc_rx_getsockopt)(struct sock *sk,
 79						 const int optname, int len,
 80						 u32 __user *optval,
 81						 int __user *optlen);
 82	int		(*ccid_hc_tx_getsockopt)(struct sock *sk,
 83						 const int optname, int len,
 84						 u32 __user *optval,
 85						 int __user *optlen);
 86};
 87
 88extern struct ccid_operations ccid2_ops;
 89#ifdef CONFIG_IP_DCCP_CCID3
 90extern struct ccid_operations ccid3_ops;
 91#endif
 92
 93int ccid_initialize_builtins(void);
 94void ccid_cleanup_builtins(void);
 95
 96struct ccid {
 97	struct ccid_operations *ccid_ops;
 98	char		       ccid_priv[];
 99};
100
101static inline void *ccid_priv(const struct ccid *ccid)
102{
103	return (void *)ccid->ccid_priv;
104}
105
106bool ccid_support_check(u8 const *ccid_array, u8 array_len);
107int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
108int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
109				  char __user *, int __user *);
110
111struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx);
112
113static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)
114{
115	struct ccid *ccid = dp->dccps_hc_rx_ccid;
116
117	if (ccid == NULL || ccid->ccid_ops == NULL)
118		return -1;
119	return ccid->ccid_ops->ccid_id;
120}
121
122static inline int ccid_get_current_tx_ccid(struct dccp_sock *dp)
123{
124	struct ccid *ccid = dp->dccps_hc_tx_ccid;
125
126	if (ccid == NULL || ccid->ccid_ops == NULL)
127		return -1;
128	return ccid->ccid_ops->ccid_id;
129}
130
131void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
132void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
133
134/*
135 * Congestion control of queued data packets via CCID decision.
136 *
137 * The TX CCID performs its congestion-control by indicating whether and when a
138 * queued packet may be sent, using the return code of ccid_hc_tx_send_packet().
139 * The following modes are supported via the symbolic constants below:
140 * - timer-based pacing    (CCID returns a delay value in milliseconds);
141 * - autonomous dequeueing (CCID internally schedules dccps_xmitlet).
142 */
143
144enum ccid_dequeueing_decision {
145	CCID_PACKET_SEND_AT_ONCE =	 0x00000,  /* "green light": no delay */
146	CCID_PACKET_DELAY_MAX =		 0x0FFFF,  /* maximum delay in msecs  */
147	CCID_PACKET_DELAY =		 0x10000,  /* CCID msec-delay mode */
148	CCID_PACKET_WILL_DEQUEUE_LATER = 0x20000,  /* CCID autonomous mode */
149	CCID_PACKET_ERR =		 0xF0000,  /* error condition */
150};
151
152static inline int ccid_packet_dequeue_eval(const int return_code)
153{
154	if (return_code < 0)
155		return CCID_PACKET_ERR;
156	if (return_code == 0)
157		return CCID_PACKET_SEND_AT_ONCE;
158	if (return_code <= CCID_PACKET_DELAY_MAX)
159		return CCID_PACKET_DELAY;
160	return return_code;
161}
162
163static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
164					 struct sk_buff *skb)
165{
166	if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
167		return ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);
168	return CCID_PACKET_SEND_AT_ONCE;
169}
170
171static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
172					  unsigned int len)
173{
174	if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
175		ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);
176}
177
178static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
179					  struct sk_buff *skb)
180{
181	if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
182		ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
183}
184
185static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
186					  struct sk_buff *skb)
187{
188	if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
189		ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
190}
191
192/**
193 * ccid_hc_tx_parse_options  -  Parse CCID-specific options sent by the receiver
194 * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
195 * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
196 * @val: value of @opt
197 * @len: length of @val in bytes
198 */
199static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
200					   u8 pkt, u8 opt, u8 *val, u8 len)
201{
202	if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
203		return 0;
204	return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
205}
206
207/**
208 * ccid_hc_rx_parse_options  -  Parse CCID-specific options sent by the sender
209 * Arguments are analogous to ccid_hc_tx_parse_options()
210 */
211static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
212					   u8 pkt, u8 opt, u8 *val, u8 len)
213{
214	if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
215		return 0;
216	return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
217}
218
219static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
220					    struct sk_buff *skb)
221{
222	if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
223		return ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
224	return 0;
225}
226
227static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
228				       struct tcp_info *info)
229{
230	if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
231		ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
232}
233
234static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
235				       struct tcp_info *info)
236{
237	if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
238		ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
239}
240
241static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
242					const int optname, int len,
243					u32 __user *optval, int __user *optlen)
244{
245	int rc = -ENOPROTOOPT;
246	if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
247		rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
248						 optval, optlen);
249	return rc;
250}
251
252static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
253					const int optname, int len,
254					u32 __user *optval, int __user *optlen)
255{
256	int rc = -ENOPROTOOPT;
257	if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
258		rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
259						 optval, optlen);
260	return rc;
261}
262#endif /* _CCID_H */
v6.2
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2#ifndef _CCID_H
  3#define _CCID_H
  4/*
  5 *  net/dccp/ccid.h
  6 *
  7 *  An implementation of the DCCP protocol
  8 *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  9 *
 10 *  CCID infrastructure
 11 */
 12
 13#include <net/sock.h>
 14#include <linux/compiler.h>
 15#include <linux/dccp.h>
 16#include <linux/list.h>
 17#include <linux/module.h>
 18
 19/* maximum value for a CCID (RFC 4340, 19.5) */
 20#define CCID_MAX		255
 21#define CCID_SLAB_NAME_LENGTH	32
 22
 23struct tcp_info;
 24
 25/**
 26 *  struct ccid_operations  -  Interface to Congestion-Control Infrastructure
 27 *
 28 *  @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.)
 29 *  @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled)
 30 *  @ccid_name: alphabetical identifier string for @ccid_id
 31 *  @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection
 32 *  @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket
 33 *
 34 *  @ccid_hc_{r,t}x_init: CCID-specific initialisation routine (before startup)
 35 *  @ccid_hc_{r,t}x_exit: CCID-specific cleanup routine (before destruction)
 36 *  @ccid_hc_rx_packet_recv: implements the HC-receiver side
 37 *  @ccid_hc_{r,t}x_parse_options: parsing routine for CCID/HC-specific options
 38 *  @ccid_hc_{r,t}x_insert_options: insert routine for CCID/HC-specific options
 39 *  @ccid_hc_tx_packet_recv: implements feedback processing for the HC-sender
 40 *  @ccid_hc_tx_send_packet: implements the sending part of the HC-sender
 41 *  @ccid_hc_tx_packet_sent: does accounting for packets in flight by HC-sender
 42 *  @ccid_hc_{r,t}x_get_info: INET_DIAG information for HC-receiver/sender
 43 *  @ccid_hc_{r,t}x_getsockopt: socket options specific to HC-receiver/sender
 44 */
 45struct ccid_operations {
 46	unsigned char		ccid_id;
 47	__u32			ccid_ccmps;
 48	const char		*ccid_name;
 49	struct kmem_cache	*ccid_hc_rx_slab,
 50				*ccid_hc_tx_slab;
 51	char			ccid_hc_rx_slab_name[CCID_SLAB_NAME_LENGTH];
 52	char			ccid_hc_tx_slab_name[CCID_SLAB_NAME_LENGTH];
 53	__u32			ccid_hc_rx_obj_size,
 54				ccid_hc_tx_obj_size;
 55	/* Interface Routines */
 56	int		(*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
 57	int		(*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
 58	void		(*ccid_hc_rx_exit)(struct sock *sk);
 59	void		(*ccid_hc_tx_exit)(struct sock *sk);
 60	void		(*ccid_hc_rx_packet_recv)(struct sock *sk,
 61						  struct sk_buff *skb);
 62	int		(*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
 63						    u8 opt, u8 *val, u8 len);
 64	int		(*ccid_hc_rx_insert_options)(struct sock *sk,
 65						     struct sk_buff *skb);
 66	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
 67						  struct sk_buff *skb);
 68	int		(*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
 69						    u8 opt, u8 *val, u8 len);
 70	int		(*ccid_hc_tx_send_packet)(struct sock *sk,
 71						  struct sk_buff *skb);
 72	void		(*ccid_hc_tx_packet_sent)(struct sock *sk,
 73						  unsigned int len);
 74	void		(*ccid_hc_rx_get_info)(struct sock *sk,
 75					       struct tcp_info *info);
 76	void		(*ccid_hc_tx_get_info)(struct sock *sk,
 77					       struct tcp_info *info);
 78	int		(*ccid_hc_rx_getsockopt)(struct sock *sk,
 79						 const int optname, int len,
 80						 u32 __user *optval,
 81						 int __user *optlen);
 82	int		(*ccid_hc_tx_getsockopt)(struct sock *sk,
 83						 const int optname, int len,
 84						 u32 __user *optval,
 85						 int __user *optlen);
 86};
 87
 88extern struct ccid_operations ccid2_ops;
 89#ifdef CONFIG_IP_DCCP_CCID3
 90extern struct ccid_operations ccid3_ops;
 91#endif
 92
 93int ccid_initialize_builtins(void);
 94void ccid_cleanup_builtins(void);
 95
 96struct ccid {
 97	struct ccid_operations *ccid_ops;
 98	char		       ccid_priv[];
 99};
100
101static inline void *ccid_priv(const struct ccid *ccid)
102{
103	return (void *)ccid->ccid_priv;
104}
105
106bool ccid_support_check(u8 const *ccid_array, u8 array_len);
107int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
108int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
109				  char __user *, int __user *);
110
111struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx);
112
113static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)
114{
115	struct ccid *ccid = dp->dccps_hc_rx_ccid;
116
117	if (ccid == NULL || ccid->ccid_ops == NULL)
118		return -1;
119	return ccid->ccid_ops->ccid_id;
120}
121
122static inline int ccid_get_current_tx_ccid(struct dccp_sock *dp)
123{
124	struct ccid *ccid = dp->dccps_hc_tx_ccid;
125
126	if (ccid == NULL || ccid->ccid_ops == NULL)
127		return -1;
128	return ccid->ccid_ops->ccid_id;
129}
130
131void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
132void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
133
134/*
135 * Congestion control of queued data packets via CCID decision.
136 *
137 * The TX CCID performs its congestion-control by indicating whether and when a
138 * queued packet may be sent, using the return code of ccid_hc_tx_send_packet().
139 * The following modes are supported via the symbolic constants below:
140 * - timer-based pacing    (CCID returns a delay value in milliseconds);
141 * - autonomous dequeueing (CCID internally schedules dccps_xmitlet).
142 */
143
144enum ccid_dequeueing_decision {
145	CCID_PACKET_SEND_AT_ONCE =	 0x00000,  /* "green light": no delay */
146	CCID_PACKET_DELAY_MAX =		 0x0FFFF,  /* maximum delay in msecs  */
147	CCID_PACKET_DELAY =		 0x10000,  /* CCID msec-delay mode */
148	CCID_PACKET_WILL_DEQUEUE_LATER = 0x20000,  /* CCID autonomous mode */
149	CCID_PACKET_ERR =		 0xF0000,  /* error condition */
150};
151
152static inline int ccid_packet_dequeue_eval(const int return_code)
153{
154	if (return_code < 0)
155		return CCID_PACKET_ERR;
156	if (return_code == 0)
157		return CCID_PACKET_SEND_AT_ONCE;
158	if (return_code <= CCID_PACKET_DELAY_MAX)
159		return CCID_PACKET_DELAY;
160	return return_code;
161}
162
163static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
164					 struct sk_buff *skb)
165{
166	if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
167		return ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);
168	return CCID_PACKET_SEND_AT_ONCE;
169}
170
171static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
172					  unsigned int len)
173{
174	if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
175		ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);
176}
177
178static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
179					  struct sk_buff *skb)
180{
181	if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
182		ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
183}
184
185static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
186					  struct sk_buff *skb)
187{
188	if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
189		ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
190}
191
192/**
193 * ccid_hc_tx_parse_options  -  Parse CCID-specific options sent by the receiver
194 * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
195 * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
196 * @val: value of @opt
197 * @len: length of @val in bytes
198 */
199static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
200					   u8 pkt, u8 opt, u8 *val, u8 len)
201{
202	if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
203		return 0;
204	return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
205}
206
207/**
208 * ccid_hc_rx_parse_options  -  Parse CCID-specific options sent by the sender
209 * Arguments are analogous to ccid_hc_tx_parse_options()
210 */
211static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
212					   u8 pkt, u8 opt, u8 *val, u8 len)
213{
214	if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
215		return 0;
216	return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
217}
218
219static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
220					    struct sk_buff *skb)
221{
222	if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
223		return ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
224	return 0;
225}
226
227static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
228				       struct tcp_info *info)
229{
230	if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
231		ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
232}
233
234static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
235				       struct tcp_info *info)
236{
237	if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
238		ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
239}
240
241static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
242					const int optname, int len,
243					u32 __user *optval, int __user *optlen)
244{
245	int rc = -ENOPROTOOPT;
246	if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
247		rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
248						 optval, optlen);
249	return rc;
250}
251
252static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
253					const int optname, int len,
254					u32 __user *optval, int __user *optlen)
255{
256	int rc = -ENOPROTOOPT;
257	if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
258		rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
259						 optval, optlen);
260	return rc;
261}
262#endif /* _CCID_H */