Deleted Added
full compact
ng_source.c (167156) ng_source.c (167160)
1/*
2 * ng_source.c
3 */
4
5/*-
6 * Copyright (c) 2005 Gleb Smirnoff <glebius@FreeBSD.org>
7 * Copyright 2002 Sandvine Inc.
8 * All rights reserved.

--- 25 unchanged lines hidden (view full) ---

34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF SANDVINE IS ADVISED OF THE POSSIBILITY OF SUCH
36 * DAMAGE.
37 *
38 * Author: Dave Chapeskie <dchapeskie@sandvine.com>
39 */
40
41#include <sys/cdefs.h>
1/*
2 * ng_source.c
3 */
4
5/*-
6 * Copyright (c) 2005 Gleb Smirnoff <glebius@FreeBSD.org>
7 * Copyright 2002 Sandvine Inc.
8 * All rights reserved.

--- 25 unchanged lines hidden (view full) ---

34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF SANDVINE IS ADVISED OF THE POSSIBILITY OF SUCH
36 * DAMAGE.
37 *
38 * Author: Dave Chapeskie <dchapeskie@sandvine.com>
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sys/netgraph/ng_source.c 167156 2007-03-01 23:16:17Z emaste $");
42__FBSDID("$FreeBSD: head/sys/netgraph/ng_source.c 167160 2007-03-02 01:44:04Z emaste $");
43
44/*
45 * This node is used for high speed packet geneneration. It queues
46 * all data recieved on its 'input' hook and when told to start via
47 * a control message it sends the packets out its 'output' hook. In
48 * this way this node can be preloaded with a packet stream which it
49 * can then send continuously as fast as possible.
50 *

--- 30 unchanged lines hidden (view full) ---

81
82/* Per node info */
83struct privdata {
84 node_p node;
85 hook_p input;
86 hook_p output;
87 struct ng_source_stats stats;
88 struct ifqueue snd_queue; /* packets to send */
43
44/*
45 * This node is used for high speed packet geneneration. It queues
46 * all data recieved on its 'input' hook and when told to start via
47 * a control message it sends the packets out its 'output' hook. In
48 * this way this node can be preloaded with a packet stream which it
49 * can then send continuously as fast as possible.
50 *

--- 30 unchanged lines hidden (view full) ---

81
82/* Per node info */
83struct privdata {
84 node_p node;
85 hook_p input;
86 hook_p output;
87 struct ng_source_stats stats;
88 struct ifqueue snd_queue; /* packets to send */
89 struct mbuf *last_packet; /* last pkt in queue */
89 struct ifnet *output_ifp;
90 struct callout intr_ch;
91 uint64_t packets; /* packets to send */
92 uint32_t queueOctets;
93 struct ng_source_embed_info embed_timestamp;
90 struct ifnet *output_ifp;
91 struct callout intr_ch;
92 uint64_t packets; /* packets to send */
93 uint32_t queueOctets;
94 struct ng_source_embed_info embed_timestamp;
95 struct ng_source_embed_cnt_info embed_counter[NG_SOURCE_COUNTERS];
94};
95typedef struct privdata *sc_p;
96
97/* Node flags */
98#define NG_SOURCE_ACTIVE (NGF_TYPE1)
99
100/* Netgraph methods */
101static ng_constructor_t ng_source_constructor;

--- 8 unchanged lines hidden (view full) ---

110static void ng_source_intr(node_p, hook_p, void *, int);
111static void ng_source_clr_data (sc_p);
112static int ng_source_start (sc_p, uint64_t);
113static void ng_source_stop (sc_p);
114static int ng_source_send (sc_p, int, int *);
115static int ng_source_store_output_ifp(sc_p, char *);
116static void ng_source_packet_mod(sc_p, struct mbuf *,
117 int, int, caddr_t, int);
96};
97typedef struct privdata *sc_p;
98
99/* Node flags */
100#define NG_SOURCE_ACTIVE (NGF_TYPE1)
101
102/* Netgraph methods */
103static ng_constructor_t ng_source_constructor;

--- 8 unchanged lines hidden (view full) ---

112static void ng_source_intr(node_p, hook_p, void *, int);
113static void ng_source_clr_data (sc_p);
114static int ng_source_start (sc_p, uint64_t);
115static void ng_source_stop (sc_p);
116static int ng_source_send (sc_p, int, int *);
117static int ng_source_store_output_ifp(sc_p, char *);
118static void ng_source_packet_mod(sc_p, struct mbuf *,
119 int, int, caddr_t, int);
120static void ng_source_mod_counter(sc_p sc,
121 struct ng_source_embed_cnt_info *cnt,
122 struct mbuf *m, int increment);
118static int ng_source_dup_mod(sc_p, struct mbuf *,
119 struct mbuf **);
120
121/* Parse type for timeval */
122static const struct ng_parse_struct_field ng_source_timeval_type_fields[] = {
123 { "tv_sec", &ng_parse_int32_type },
124 { "tv_usec", &ng_parse_int32_type },
125 { NULL }

--- 14 unchanged lines hidden (view full) ---

140/* Parse type for struct ng_source_embed_info */
141static const struct ng_parse_struct_field ng_source_embed_type_fields[] =
142 NG_SOURCE_EMBED_TYPE_INFO;
143static const struct ng_parse_type ng_source_embed_type = {
144 &ng_parse_struct_type,
145 &ng_source_embed_type_fields
146};
147
123static int ng_source_dup_mod(sc_p, struct mbuf *,
124 struct mbuf **);
125
126/* Parse type for timeval */
127static const struct ng_parse_struct_field ng_source_timeval_type_fields[] = {
128 { "tv_sec", &ng_parse_int32_type },
129 { "tv_usec", &ng_parse_int32_type },
130 { NULL }

--- 14 unchanged lines hidden (view full) ---

145/* Parse type for struct ng_source_embed_info */
146static const struct ng_parse_struct_field ng_source_embed_type_fields[] =
147 NG_SOURCE_EMBED_TYPE_INFO;
148static const struct ng_parse_type ng_source_embed_type = {
149 &ng_parse_struct_type,
150 &ng_source_embed_type_fields
151};
152
153/* Parse type for struct ng_source_embed_cnt_info */
154static const struct ng_parse_struct_field ng_source_embed_cnt_type_fields[] =
155 NG_SOURCE_EMBED_CNT_TYPE_INFO;
156static const struct ng_parse_type ng_source_embed_cnt_type = {
157 &ng_parse_struct_type,
158 &ng_source_embed_cnt_type_fields
159};
160
148/* List of commands and how to convert arguments to/from ASCII */
149static const struct ng_cmdlist ng_source_cmds[] = {
150 {
151 NGM_SOURCE_COOKIE,
152 NGM_SOURCE_GET_STATS,
153 "getstats",
154 NULL,
155 &ng_source_stats_type

--- 56 unchanged lines hidden (view full) ---

212 },
213 {
214 NGM_SOURCE_COOKIE,
215 NGM_SOURCE_GET_TIMESTAMP,
216 "gettimestamp",
217 NULL,
218 &ng_source_embed_type
219 },
161/* List of commands and how to convert arguments to/from ASCII */
162static const struct ng_cmdlist ng_source_cmds[] = {
163 {
164 NGM_SOURCE_COOKIE,
165 NGM_SOURCE_GET_STATS,
166 "getstats",
167 NULL,
168 &ng_source_stats_type

--- 56 unchanged lines hidden (view full) ---

225 },
226 {
227 NGM_SOURCE_COOKIE,
228 NGM_SOURCE_GET_TIMESTAMP,
229 "gettimestamp",
230 NULL,
231 &ng_source_embed_type
232 },
233 {
234 NGM_SOURCE_COOKIE,
235 NGM_SOURCE_SET_COUNTER,
236 "setcounter",
237 &ng_source_embed_cnt_type,
238 NULL
239 },
240 {
241 NGM_SOURCE_COOKIE,
242 NGM_SOURCE_GET_COUNTER,
243 "getcounter",
244 &ng_parse_uint8_type,
245 &ng_source_embed_cnt_type
246 },
220 { 0 }
221};
222
223/* Netgraph type descriptor */
224static struct ng_type ng_source_typestruct = {
225 .version = NG_ABI_VERSION,
226 .name = NG_SOURCE_NODE_TYPE,
227 .constructor = ng_source_constructor,

--- 193 unchanged lines hidden (view full) ---

421 error = ENOMEM;
422 goto done;
423 }
424 embed = (struct ng_source_embed_info *)resp->data;
425 bcopy(&sc->embed_timestamp, embed, sizeof(*embed));
426
427 break;
428 }
247 { 0 }
248};
249
250/* Netgraph type descriptor */
251static struct ng_type ng_source_typestruct = {
252 .version = NG_ABI_VERSION,
253 .name = NG_SOURCE_NODE_TYPE,
254 .constructor = ng_source_constructor,

--- 193 unchanged lines hidden (view full) ---

448 error = ENOMEM;
449 goto done;
450 }
451 embed = (struct ng_source_embed_info *)resp->data;
452 bcopy(&sc->embed_timestamp, embed, sizeof(*embed));
453
454 break;
455 }
456 case NGM_SOURCE_SET_COUNTER:
457 {
458 struct ng_source_embed_cnt_info *embed;
459
460 embed = (struct ng_source_embed_cnt_info *)msg->data;
461 if (embed->index >= NG_SOURCE_COUNTERS ||
462 !(embed->width == 1 || embed->width == 2 ||
463 embed->width == 4)) {
464 error = EINVAL;
465 goto done;
466 }
467 bcopy(embed, &sc->embed_counter[embed->index],
468 sizeof(*embed));
469
470 break;
471 }
472 case NGM_SOURCE_GET_COUNTER:
473 {
474 uint8_t index = *(uint8_t *)msg->data;
475 struct ng_source_embed_cnt_info *embed;
476
477 if (index >= NG_SOURCE_COUNTERS) {
478 error = EINVAL;
479 goto done;
480 }
481 NG_MKRESPONSE(resp, msg, sizeof(*embed), M_DONTWAIT);
482 if (resp == NULL) {
483 error = ENOMEM;
484 goto done;
485 }
486 embed = (struct ng_source_embed_cnt_info *)resp->data;
487 bcopy(&sc->embed_counter[index], embed, sizeof(*embed));
488
489 break;
490 }
429 default:
430 error = EINVAL;
431 break;
432 }
433 break;
434 case NGM_ETHER_COOKIE:
435 if (!(msg->header.flags & NGF_RESP)) {
436 error = EINVAL;

--- 53 unchanged lines hidden (view full) ---

490 return (error);
491 }
492 KASSERT(hook == sc->input, ("%s: no hook!", __func__));
493
494 /* Enqueue packet. */
495 /* XXX should we check IF_QFULL() ? */
496 _IF_ENQUEUE(&sc->snd_queue, m);
497 sc->queueOctets += m->m_pkthdr.len;
491 default:
492 error = EINVAL;
493 break;
494 }
495 break;
496 case NGM_ETHER_COOKIE:
497 if (!(msg->header.flags & NGF_RESP)) {
498 error = EINVAL;

--- 53 unchanged lines hidden (view full) ---

552 return (error);
553 }
554 KASSERT(hook == sc->input, ("%s: no hook!", __func__));
555
556 /* Enqueue packet. */
557 /* XXX should we check IF_QFULL() ? */
558 _IF_ENQUEUE(&sc->snd_queue, m);
559 sc->queueOctets += m->m_pkthdr.len;
560 sc->last_packet = m;
498
499 return (0);
500}
501
502/*
503 * Shutdown processing
504 */
505static int

--- 89 unchanged lines hidden (view full) ---

595
596 for (;;) {
597 _IF_DEQUEUE(&sc->snd_queue, m);
598 if (m == NULL)
599 break;
600 NG_FREE_M(m);
601 }
602 sc->queueOctets = 0;
561
562 return (0);
563}
564
565/*
566 * Shutdown processing
567 */
568static int

--- 89 unchanged lines hidden (view full) ---

658
659 for (;;) {
660 _IF_DEQUEUE(&sc->snd_queue, m);
661 if (m == NULL)
662 break;
663 NG_FREE_M(m);
664 }
665 sc->queueOctets = 0;
666 sc->last_packet = 0;
603}
604
605/*
606 * Start sending queued data out the output hook
607 */
608static int
609ng_source_start(sc_p sc, uint64_t packets)
610{

--- 145 unchanged lines hidden (view full) ---

756 /* Can't modify beyond end of packet. */
757 /* TODO: Pad packet for this case. */
758 if (offset + len > m->m_len)
759 return;
760
761 bcopy(cp, mtod_off(m, offset, caddr_t), len);
762}
763
667}
668
669/*
670 * Start sending queued data out the output hook
671 */
672static int
673ng_source_start(sc_p sc, uint64_t packets)
674{

--- 145 unchanged lines hidden (view full) ---

820 /* Can't modify beyond end of packet. */
821 /* TODO: Pad packet for this case. */
822 if (offset + len > m->m_len)
823 return;
824
825 bcopy(cp, mtod_off(m, offset, caddr_t), len);
826}
827
828static void
829ng_source_mod_counter(sc_p sc, struct ng_source_embed_cnt_info *cnt,
830 struct mbuf *m, int increment)
831{
832 caddr_t cp;
833 uint32_t val;
834
835 val = htonl(cnt->next_val);
836 cp = (caddr_t)&val + sizeof(val) - cnt->width;
837 ng_source_packet_mod(sc, m, cnt->offset, cnt->width, cp, cnt->flags);
838
839 if (increment) {
840 cnt->next_val += increment;
841
842 if (increment > 0 && cnt->next_val > cnt->max_val) {
843 cnt->next_val = cnt->min_val - 1 +
844 (cnt->next_val - cnt->max_val);
845 if (cnt->next_val > cnt->max_val)
846 cnt->next_val = cnt->max_val;
847 } else if (increment < 0 && cnt->next_val < cnt->min_val) {
848 cnt->next_val = cnt->max_val + 1 +
849 (cnt->next_val - cnt->min_val);
850 if (cnt->next_val < cnt->min_val)
851 cnt->next_val = cnt->max_val;
852 }
853 }
854}
855
764static int
765ng_source_dup_mod(sc_p sc, struct mbuf *m0, struct mbuf **m_ptr)
766{
767 struct mbuf *m;
856static int
857ng_source_dup_mod(sc_p sc, struct mbuf *m0, struct mbuf **m_ptr)
858{
859 struct mbuf *m;
860 struct ng_source_embed_cnt_info *cnt;
768 struct ng_source_embed_info *ts;
769 int modify;
770 int error = 0;
861 struct ng_source_embed_info *ts;
862 int modify;
863 int error = 0;
864 int i, increment;
771
772 /* Are we going to modify packets? */
773 modify = sc->embed_timestamp.flags & NGM_SOURCE_EMBED_ENABLE;
865
866 /* Are we going to modify packets? */
867 modify = sc->embed_timestamp.flags & NGM_SOURCE_EMBED_ENABLE;
868 for (i = 0; !modify && i < NG_SOURCE_COUNTERS; ++i)
869 modify = sc->embed_counter[i].flags & NGM_SOURCE_EMBED_ENABLE;
774
775 /* Duplicate the packet. */
776 if (modify)
777 m = m_dup(m0, M_DONTWAIT);
778 else
779 m = m_copypacket(m0, M_DONTWAIT);
780 if (m == NULL) {
781 error = ENOBUFS;
782 goto done;
783 }
784 *m_ptr = m;
785
786 if (!modify)
787 goto done;
788
789 /* Modify the copied packet for sending. */
790 KASSERT(M_WRITABLE(m), ("%s: packet not writable", __func__));
791
870
871 /* Duplicate the packet. */
872 if (modify)
873 m = m_dup(m0, M_DONTWAIT);
874 else
875 m = m_copypacket(m0, M_DONTWAIT);
876 if (m == NULL) {
877 error = ENOBUFS;
878 goto done;
879 }
880 *m_ptr = m;
881
882 if (!modify)
883 goto done;
884
885 /* Modify the copied packet for sending. */
886 KASSERT(M_WRITABLE(m), ("%s: packet not writable", __func__));
887
888 for (i = 0; i < NG_SOURCE_COUNTERS; ++i) {
889 cnt = &sc->embed_counter[i];
890 if (cnt->flags & NGM_SOURCE_EMBED_ENABLE) {
891 if ((cnt->flags & NGM_SOURCE_INC_CNT_PER_LIST) == 0 ||
892 sc->last_packet == m0)
893 increment = cnt->increment;
894 else
895 increment = 0;
896 ng_source_mod_counter(sc, cnt, m, increment);
897 }
898 }
899
792 ts = &sc->embed_timestamp;
793 if (ts->flags & NGM_SOURCE_EMBED_ENABLE) {
794 struct timeval now;
795 getmicrotime(&now);
796 now.tv_sec = htonl(now.tv_sec);
797 now.tv_usec = htonl(now.tv_usec);
798 ng_source_packet_mod(sc, m, ts->offset, sizeof (now),
799 (caddr_t)&now, ts->flags);
800 }
801
802done:
803 return(error);
804}
900 ts = &sc->embed_timestamp;
901 if (ts->flags & NGM_SOURCE_EMBED_ENABLE) {
902 struct timeval now;
903 getmicrotime(&now);
904 now.tv_sec = htonl(now.tv_sec);
905 now.tv_usec = htonl(now.tv_usec);
906 ng_source_packet_mod(sc, m, ts->offset, sizeof (now),
907 (caddr_t)&now, ts->flags);
908 }
909
910done:
911 return(error);
912}