1/* 2 * ng_source.c 3 * 4 * Copyright 2002 Sandvine Inc. 5 * All rights reserved. 6 * 7 * Subject to the following obligations and disclaimer of warranty, use and 8 * redistribution of this software, in source or object code forms, with or |
9 * without modifications are expressly permitted by Sandvine Inc.; provided, |
10 * however, that: |
11 * 1. Any and all reproductions of the source or object code must include the 12 * copyright notice above and the following disclaimer of warranties; and |
13 * 2. No rights are granted, in any manner or form, to use Sandvine Inc. |
14 * trademarks, including the mark "SANDVINE" on advertising, endorsements, 15 * or otherwise except as such appears in the above copyright notice or in |
16 * the software. 17 * 18 * THIS SOFTWARE IS BEING PROVIDED BY SANDVINE "AS IS", AND TO THE MAXIMUM |
19 * EXTENT PERMITTED BY LAW, SANDVINE MAKES NO REPRESENTATIONS OR WARRANTIES, 20 * EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, 21 * ANY AND ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
22 * PURPOSE, OR NON-INFRINGEMENT. SANDVINE DOES NOT WARRANT, GUARANTEE, OR 23 * MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE 24 * USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY 25 * OR OTHERWISE. IN NO EVENT SHALL SANDVINE BE LIABLE FOR ANY DAMAGES 26 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING |
27 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
28 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 29 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF SANDVINE IS ADVISED OF THE POSSIBILITY OF SUCH 33 * DAMAGE. 34 * 35 * Author: Dave Chapeskie <dchapeskie@sandvine.com> 36 * |
37 * $FreeBSD: head/sys/netgraph/ng_source.c 106319 2002-11-02 01:26:28Z julian $ |
38 */ 39 40/* 41 * This node is used for high speed packet geneneration. It queues 42 * all data recieved on it's 'input' hook and when told to start via 43 * a control message it sends the packets out it's 'output' hook. In 44 * this way this node can be preloaded with a packet stream which is 45 * continuously sent. --- 33 unchanged lines hidden (view full) --- 79}; 80 81/* Per node info */ 82struct privdata { 83 node_p node; 84 struct source_hookinfo input; 85 struct source_hookinfo output; 86 struct ng_source_stats stats; |
87 struct ifqueue snd_queue; /* packets to send */ |
88 struct ifnet *output_ifp; 89 struct callout_handle intr_ch; |
90 u_int64_t packets; /* packets to send */ |
91 u_int32_t queueOctets; 92}; 93typedef struct privdata *sc_p; 94 95/* Node flags */ 96#define NG_SOURCE_ACTIVE (NGF_TYPE1) 97 98/* XXX */ --- 180 unchanged lines hidden (view full) --- 279 if (msg->header.cmd != NGM_SOURCE_CLR_STATS) { 280 NG_MKRESPONSE(resp, msg, 281 sizeof(*stats), M_NOWAIT); 282 if (resp == NULL) { 283 error = ENOMEM; 284 goto done; 285 } 286 sc->stats.queueOctets = sc->queueOctets; |
287 sc->stats.queueFrames = sc->snd_queue.ifq_len; |
288 if ((sc->node->flags & NG_SOURCE_ACTIVE) 289 && !timevalisset(&sc->stats.endTime)) { |
290 getmicrotime(&sc->stats.elapsedTime); |
291 timevalsub(&sc->stats.elapsedTime, |
292 &sc->stats.startTime); |
293 } |
294 stats = (struct ng_source_stats *)resp->data; |
295 bcopy(&sc->stats, stats, sizeof(* stats)); 296 } 297 if (msg->header.cmd != NGM_SOURCE_GET_STATS) 298 bzero(&sc->stats, sizeof(sc->stats)); 299 } 300 break; 301 case NGM_SOURCE_START: 302 { 303 u_int64_t packets = *(u_int64_t *)msg->data; 304 if (sc->output.hook == NULL) { |
305 printf("%s: start on node with no output hook\n" 306 , __FUNCTION__); |
307 error = EINVAL; 308 break; 309 } 310 /* TODO validation of packets */ 311 sc->packets = packets; 312 ng_source_start(sc); 313 } 314 break; --- 27 unchanged lines hidden (view full) --- 342 * 343 * If data comes in the input hook, enqueue it on the send queue. 344 * If data comes in the output hook, discard it. 345 */ 346static int 347ng_source_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) 348{ 349 const sc_p sc = hook->node->private; |
350 struct source_hookinfo *const hinfo; |
351 int error = 0; 352 |
353 hinfo = (struct source_hookinfo *) hook->private; |
354 KASSERT(sc != NULL, ("%s: null node private", __FUNCTION__)); 355 KASSERT(hinfo != NULL, ("%s: null hook info", __FUNCTION__)); 356 357 /* Which hook? */ 358 if (hinfo == &sc->output) { 359 /* discard */ 360 NG_FREE_DATA(m, meta); 361 return (error); --- 38 unchanged lines hidden (view full) --- 400} 401 402/* 403 * Hook disconnection 404 */ 405static int 406ng_source_disconnect(hook_p hook) 407{ |
408 struct source_hookinfo *const hinfo; 409 sc_p sc; |
410 |
411 hinfo = (struct source_hookinfo *) hook->private; 412 sc = (sc_p) hinfo->hook->node->private; |
413 KASSERT(sc != NULL, ("%s: null node private", __FUNCTION__)); 414 hinfo->hook = NULL; 415 if (hook->node->numhooks == 0 || hinfo == &sc->output) 416 ng_rmnode(hook->node); 417 return (0); 418} 419 420/* --- 7 unchanged lines hidden (view full) --- 428 struct ifnet *ifp; 429 u_int32_t if_index; 430 int error = 0; 431 int s; 432 433 sc->output_ifp = NULL; 434 435 /* Ask the attached node for the connected interface's index */ |
436 NG_MKMESSAGE(msg, NGM_ETHER_COOKIE, NGM_ETHER_GET_IFINDEX, 0, M_NOWAIT); |
437 if (msg == NULL) 438 return (ENOBUFS); 439 440 error = ng_send_msg(sc->node, msg, NG_SOURCE_HOOK_OUTPUT, &rsp); 441 if (error != 0) 442 return (error); 443 444 if (rsp == NULL) --- 8 unchanged lines hidden (view full) --- 453 * local to if_attach() 454 */ 455 TAILQ_FOREACH(ifp, &ifnet, if_link) { 456 if (ifp->if_index == if_index) 457 break; 458 } 459 460 if (ifp == NULL) { |
461 printf("%s: can't find interface %d\n", __FUNCTION__, if_index); |
462 return (EINVAL); 463 } 464 sc->output_ifp = ifp; 465 466#if 1 467 /* XXX mucking with a drivers ifqueue size is ugly but we need it 468 * to queue a lot of packets to get close to line rate on a gigabit 469 * interface with small packets. 470 * XXX we should restore the original value at stop or disconnect 471 */ 472 s = splimp(); /* XXX is this required? */ 473 if (ifp->if_snd.ifq_maxlen < NG_SOURCE_DRIVER_IFQ_MAXLEN) 474 { 475 printf("ng_source: changing ifq_maxlen from %d to %d\n", |
476 ifp->if_snd.ifq_maxlen, NG_SOURCE_DRIVER_IFQ_MAXLEN); |
477 ifp->if_snd.ifq_maxlen = NG_SOURCE_DRIVER_IFQ_MAXLEN; 478 } 479 splx(s); 480#endif 481 return (0); 482} 483 484/* --- 38 unchanged lines hidden (view full) --- 523 */ 524static void 525ng_source_start (sc_p sc) 526{ 527 SPLASSERT(net, __FUNCTION__); 528 KASSERT(sc->output.hook != NULL, 529 ("%s: output hook unconnected", __FUNCTION__)); 530 if ((sc->node->flags & NG_SOURCE_ACTIVE) == 0) { |
531 if (sc->output_ifp == NULL && ng_source_get_output_ifp(sc) != 0) |
532 return; 533 ng_source_set_autosrc(sc, 0); 534 sc->node->flags |= NG_SOURCE_ACTIVE; 535 timevalclear(&sc->stats.elapsedTime); 536 timevalclear(&sc->stats.endTime); 537 getmicrotime(&sc->stats.startTime); 538 sc->intr_ch = timeout(ng_source_intr, sc, 0); 539 } --- 41 unchanged lines hidden (view full) --- 581 ifq = &sc->output_ifp->if_snd; 582 packets = ifq->ifq_maxlen - ifq->ifq_len; 583 ng_source_send(sc, packets, NULL); 584 if (sc->packets == 0) { 585 int s = splnet(); 586 ng_source_stop(sc); 587 splx(s); 588 } else |
589 sc->intr_ch = timeout(ng_source_intr, sc, NG_SOURCE_INTR_TICKS); |
590} 591 592/* 593 * Send packets out our output hook 594 */ 595static int 596ng_source_send (sc_p sc, int tosend, int *sent_p) 597{ --- 66 unchanged lines hidden --- |