4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/atomic.h>
28 #include <sys/systm.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <sys/modctl.h>
32 #include <sys/sunddi.h>
34 #include <ipp/ipp_config.h>
35 #include <inet/common.h>
36 #include <ipp/dlcosmk/dlcosmk_impl.h>
38 #define D_SM_COMMENT "IPP dlcosmk marker module"
40 /* DDI file for dlcosmk ipp module */
42 static int dlcosmk_create_action(ipp_action_id_t
, nvlist_t
**, ipp_flags_t
);
43 static int dlcosmk_modify_action(ipp_action_id_t
, nvlist_t
**, ipp_flags_t
);
44 static int dlcosmk_destroy_action(ipp_action_id_t
, ipp_flags_t
);
45 static int dlcosmk_info(ipp_action_id_t
, int (*)(nvlist_t
*, void *), void *,
47 static int dlcosmk_invoke_action(ipp_action_id_t
, ipp_packet_t
*);
49 static int dlcosmk_statinit(ipp_action_id_t
, dlcosmk_data_t
*);
50 static int dlcosmk_update_stats(ipp_stat_t
*, void *, int);
52 /* Entry points for this IPP module */
53 ipp_ops_t dlcosmk_ops
= {
55 dlcosmk_create_action
, /* ippo_action_create */
56 dlcosmk_modify_action
, /* ippo_action_modify */
57 dlcosmk_destroy_action
, /* ippo_action_destroy */
58 dlcosmk_info
, /* ippo_action_info */
59 dlcosmk_invoke_action
/* ippo_action_invoke */
62 extern struct mod_ops mod_ippops
;
65 * Module linkage information for the kernel.
67 static struct modlipp modlipp
= {
73 static struct modlinkage modlinkage
= {
83 return (mod_install(&modlinkage
));
89 return (mod_remove(&modlinkage
));
93 _info(struct modinfo
*modinfop
)
95 return (mod_info(&modlinkage
, modinfop
));
99 dlcosmk_create_action(ipp_action_id_t aid
, nvlist_t
**nvlpp
,
103 dlcosmk_data_t
*dlcosmk_data
;
106 uint32_t bstats
, param
;
108 ASSERT((nvlpp
!= NULL
) && (*nvlpp
!= NULL
));
111 *nvlpp
= NULL
; /* nvlist should be NULL on return */
113 if ((dlcosmk_data
= kmem_zalloc(DLCOSMK_DATA_SZ
, KM_NOSLEEP
)) == NULL
) {
118 /* parse next action name */
119 if ((err
= nvlist_lookup_string(nvlp
, DLCOSMK_NEXT_ACTION_NAME
,
120 &next_action
)) != 0) {
122 dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
123 "next_action name missing\n"));
124 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
127 if ((dlcosmk_data
->next_action
=
128 ipp_action_lookup(next_action
)) == IPP_ACTION_INVAL
) {
130 dlcosmk0dbg(("dlcosmk_create_action: next_action invalid\n"));
131 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
135 /* parse cos - from the config file */
136 if ((err
= nvlist_lookup_byte(nvlp
, DLCOSMK_COS
,
137 &dlcosmk_data
->usr_pri
)) != 0) {
139 dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
141 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
145 /* parse b_band - mapped from cos */
146 if ((err
= nvlist_lookup_uint32(nvlp
, DLCOSMK_BAND
, ¶m
)) != 0) {
148 dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
149 "b_band missing\n"));
150 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
153 dlcosmk_data
->b_band
= param
;
155 /* parse dl_priority.dl_max - mapped from cos */
156 if ((err
= nvlist_lookup_uint32(nvlp
, DLCOSMK_PRI
, ¶m
)) != 0) {
158 dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
159 "dl_priority missing\n"));
160 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
163 dlcosmk_data
->dl_max
= param
;
165 /* parse gather_stats boolean */
166 if ((err
= nvlist_lookup_uint32(nvlp
, IPP_ACTION_STATS_ENABLE
, &bstats
))
168 dlcosmk_data
->gather_stats
= B_FALSE
;
170 /* If stats is needed, initialize the stats structure */
171 dlcosmk_data
->gather_stats
= (bstats
!= 0) ? B_TRUE
: B_FALSE
;
172 if (dlcosmk_data
->gather_stats
) {
173 if ((err
= dlcosmk_statinit(aid
, dlcosmk_data
)) != 0) {
175 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
181 /* Free the nvlist */
184 /* set action chain reference */
185 if ((err
= ipp_action_ref(aid
, dlcosmk_data
->next_action
,
187 dlcosmk0dbg(("dlcosmk_create_action: ipp_action_ref " \
188 "returned with error %d\n", err
));
189 ipp_stat_destroy(dlcosmk_data
->stats
);
190 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
194 ipp_action_set_ptr(aid
, (void *)dlcosmk_data
);
199 dlcosmk_modify_action(ipp_action_id_t aid
, nvlist_t
**nvlpp
, ipp_flags_t flags
)
203 uint32_t band
, dlpri
;
206 char *next_action_name
;
207 ipp_action_id_t next_action
;
208 dlcosmk_data_t
*dlcosmk_data
;
211 ASSERT((nvlpp
!= NULL
) && (*nvlpp
!= NULL
));
214 *nvlpp
= NULL
; /* nvlist should be NULL when this returns */
216 if ((err
= nvlist_lookup_byte(nvlp
, IPP_CONFIG_TYPE
, &config_type
))
219 dlcosmk0dbg(("dlcosmk_modify_action: invalid configuration "\
224 if (config_type
!= IPP_SET
) {
226 dlcosmk0dbg(("dlcosmk_modify_action: invalid configuration "\
227 "type %d\n", config_type
));
231 dlcosmk_data
= (dlcosmk_data_t
*)ipp_action_get_ptr(aid
);
232 ASSERT(dlcosmk_data
!= NULL
);
234 /* parse next action name, if present */
235 if ((err
= nvlist_lookup_string(nvlp
, DLCOSMK_NEXT_ACTION_NAME
,
236 &next_action_name
)) == 0) {
237 /* lookup action name to get action id */
238 if ((next_action
= ipp_action_lookup(next_action_name
))
239 == IPP_ACTION_INVAL
) {
241 dlcosmk0dbg(("dlcosmk_modify_action: next_action "\
245 /* reference new action */
246 if ((err
= ipp_action_ref(aid
, next_action
, flags
)) != 0) {
248 dlcosmk0dbg(("dlcosmk_modify_action: ipp_action_ref "\
249 "returned with error %d\n", err
));
252 /* unref old action */
253 err
= ipp_action_unref(aid
, dlcosmk_data
->next_action
, flags
);
255 dlcosmk_data
->next_action
= next_action
;
258 /* parse cos, if present */
259 if ((err
= nvlist_lookup_byte(nvlp
, DLCOSMK_COS
, &cos
)) == 0) {
261 /* parse b_band, mapped from cos */
262 if ((err
= nvlist_lookup_uint32(nvlp
, DLCOSMK_BAND
,
265 dlcosmk0dbg(("dlcosmk_modify_action: b_band not "\
270 /* parse dl_priority, mapped from cos */
271 if ((err
= nvlist_lookup_uint32(nvlp
, DLCOSMK_PRI
,
274 dlcosmk0dbg(("dlcosmk_modify_action: dl_priority not "\
279 /* Have all the three values, change them */
280 dlcosmk_data
->usr_pri
= cos
;
281 dlcosmk_data
->b_band
= band
;
282 dlcosmk_data
->dl_max
= dlpri
;
286 /* parse gather_stats boolean, if present */
287 if ((err
= nvlist_lookup_uint32(nvlp
, IPP_ACTION_STATS_ENABLE
, &bstats
))
289 boolean_t val
= (bstats
!= 0) ? B_TRUE
: B_FALSE
;
290 /* Turning on stats */
291 if (!dlcosmk_data
->gather_stats
&& val
) {
292 if ((err
= dlcosmk_statinit(aid
, dlcosmk_data
)) != 0) {
296 /* Turning off stats */
297 } else if (!val
&& dlcosmk_data
->gather_stats
) {
298 ipp_stat_destroy(dlcosmk_data
->stats
);
301 dlcosmk_data
->gather_stats
= val
;
310 dlcosmk_destroy_action(ipp_action_id_t aid
, ipp_flags_t flags
)
312 dlcosmk_data_t
*dlcosmk_data
;
315 dlcosmk_data
= (dlcosmk_data_t
*)ipp_action_get_ptr(aid
);
316 ASSERT(dlcosmk_data
!= NULL
);
318 /* Destroy stats, if gathered */
319 if (dlcosmk_data
->gather_stats
) {
320 ipp_stat_destroy(dlcosmk_data
->stats
);
323 /* unreference the action */
324 err
= ipp_action_unref(aid
, dlcosmk_data
->next_action
, flags
);
327 kmem_free(dlcosmk_data
, DLCOSMK_DATA_SZ
);
332 dlcosmk_invoke_action(ipp_action_id_t aid
, ipp_packet_t
*packet
)
334 dlcosmk_data_t
*dlcosmk_data
;
339 ASSERT(packet
!= NULL
);
341 /* get mblk from ipp_packet structure */
342 mp
= ipp_packet_get_data(packet
);
343 priv
= (ip_priv_t
*)ipp_packet_get_private(packet
);
345 dlcosmk_data
= (dlcosmk_data_t
*)ipp_action_get_ptr(aid
);
346 ASSERT(dlcosmk_data
!= NULL
);
348 /* dlcosmk packet as configured */
349 if ((err
= dlcosmk_process(&mp
, dlcosmk_data
, priv
->ill_index
,
353 /* return packet with next action set */
354 return (ipp_packet_next(packet
, dlcosmk_data
->next_action
));
359 dlcosmk_statinit(ipp_action_id_t aid
, dlcosmk_data_t
*dlcosmk_data
)
362 dlcosmk_stat_t
*statp
;
364 /* install stats entry */
365 if ((err
= ipp_stat_create(aid
, DLCOSMK_STATS_STRING
,
366 DLCOSMK_STATS_COUNT
, dlcosmk_update_stats
, dlcosmk_data
,
367 &dlcosmk_data
->stats
)) != 0) {
368 dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_create " \
369 "returned with error %d\n", err
));
373 statp
= (dlcosmk_stat_t
*)(dlcosmk_data
->stats
)->ipps_data
;
374 ASSERT(statp
!= NULL
);
376 if ((err
= ipp_stat_named_init(dlcosmk_data
->stats
, "npackets",
377 IPP_STAT_UINT64
, &statp
->npackets
)) != 0) {
378 dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
379 "returned with error %d\n", err
));
383 if ((err
= ipp_stat_named_init(dlcosmk_data
->stats
, "ipackets",
384 IPP_STAT_UINT64
, &statp
->ipackets
)) != 0) {
385 dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
386 "returned with error %d\n", err
));
390 if ((err
= ipp_stat_named_init(dlcosmk_data
->stats
, "epackets",
391 IPP_STAT_UINT64
, &statp
->epackets
)) != 0) {
392 dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
393 "returned with error %d\n", err
));
397 if ((err
= ipp_stat_named_init(dlcosmk_data
->stats
, "usr_pri",
398 IPP_STAT_INT32
, &statp
->usr_pri
)) != 0) {
399 dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
400 "returned with error %d", err
));
404 if ((err
= ipp_stat_named_init(dlcosmk_data
->stats
, "b_band",
405 IPP_STAT_INT32
, &statp
->b_band
)) != 0) {
406 dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
407 "returned with error %d\n", err
));
411 if ((err
= ipp_stat_named_init(dlcosmk_data
->stats
, "dl_max",
412 IPP_STAT_INT32
, &statp
->dl_max
)) != 0) {
413 dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
414 "returned with error %d\n", err
));
418 ipp_stat_install(dlcosmk_data
->stats
);
423 dlcosmk_update_stats(ipp_stat_t
*sp
, void *arg
, int rw
)
425 dlcosmk_data_t
*dlcosmk_data
= (dlcosmk_data_t
*)arg
;
426 dlcosmk_stat_t
*snames
= (dlcosmk_stat_t
*)sp
->ipps_data
;
427 uint32_t upri
, bband
;
429 ASSERT(dlcosmk_data
!= NULL
);
430 ASSERT(snames
!= NULL
);
432 upri
= dlcosmk_data
->usr_pri
;
433 bband
= dlcosmk_data
->b_band
;
435 (void) ipp_stat_named_op(&snames
->npackets
, &dlcosmk_data
->npackets
,
437 (void) ipp_stat_named_op(&snames
->ipackets
, &dlcosmk_data
->ipackets
,
439 (void) ipp_stat_named_op(&snames
->epackets
, &dlcosmk_data
->epackets
,
441 (void) ipp_stat_named_op(&snames
->usr_pri
, &upri
, rw
);
442 (void) ipp_stat_named_op(&snames
->b_band
, &bband
, rw
);
443 (void) ipp_stat_named_op(&snames
->dl_max
, &dlcosmk_data
->dl_max
, rw
);
450 dlcosmk_info(ipp_action_id_t aid
, int (*fn
)(nvlist_t
*, void *), void *arg
,
454 dlcosmk_data_t
*dlcosmk_data
;
460 dlcosmk_data
= (dlcosmk_data_t
*)ipp_action_get_ptr(aid
);
461 ASSERT(dlcosmk_data
!= NULL
);
463 /* allocate nvlist to be passed back */
464 if ((err
= nvlist_alloc(&nvlp
, NV_UNIQUE_NAME
, KM_NOSLEEP
)) != 0) {
465 dlcosmk0dbg(("dlcosmk_info: error allocating memory\n"));
469 /* look up next action with the next action id */
470 if ((err
= ipp_action_name(dlcosmk_data
->next_action
,
471 &next_action
)) != 0) {
472 dlcosmk0dbg(("dlcosmk_info: next action not available\n"));
477 /* add next action name */
478 if ((err
= nvlist_add_string(nvlp
, DLCOSMK_NEXT_ACTION_NAME
,
479 next_action
)) != 0) {
480 dlcosmk0dbg(("dlcosmk_info: error adding next action\n"));
482 kmem_free(next_action
, (strlen(next_action
) + 1));
486 /* free action name */
487 kmem_free(next_action
, (strlen(next_action
) + 1));
489 /* add config type */
490 if ((err
= nvlist_add_byte(nvlp
, IPP_CONFIG_TYPE
, IPP_SET
)) != 0) {
491 dlcosmk0dbg(("dlcosmk_info: error adding config. type\n"));
496 /* just give the cos, since that is what is provided in the config */
497 if ((err
= nvlist_add_byte(nvlp
, DLCOSMK_COS
, dlcosmk_data
->usr_pri
))
499 dlcosmk0dbg(("dlcosmk_info: error adding cos\n"));
504 /* add gather stats boolean */
505 if ((err
= nvlist_add_uint32(nvlp
, IPP_ACTION_STATS_ENABLE
,
506 (dlcosmk_data
->gather_stats
? 1 : 0))) != 0) {
507 dlcosmk0dbg(("dlcosmk_info: error adding stats status\n"));
512 /* call back with nvlist */