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} |