summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_source.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph/ng_source.c')
-rw-r--r--sys/netgraph/ng_source.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/sys/netgraph/ng_source.c b/sys/netgraph/ng_source.c
index df983eb..0cc76d6 100644
--- a/sys/netgraph/ng_source.c
+++ b/sys/netgraph/ng_source.c
@@ -86,11 +86,13 @@ struct privdata {
hook_p output;
struct ng_source_stats stats;
struct ifqueue snd_queue; /* packets to send */
+ struct mbuf *last_packet; /* last pkt in queue */
struct ifnet *output_ifp;
struct callout intr_ch;
uint64_t packets; /* packets to send */
uint32_t queueOctets;
struct ng_source_embed_info embed_timestamp;
+ struct ng_source_embed_cnt_info embed_counter[NG_SOURCE_COUNTERS];
};
typedef struct privdata *sc_p;
@@ -115,6 +117,9 @@ static int ng_source_send (sc_p, int, int *);
static int ng_source_store_output_ifp(sc_p, char *);
static void ng_source_packet_mod(sc_p, struct mbuf *,
int, int, caddr_t, int);
+static void ng_source_mod_counter(sc_p sc,
+ struct ng_source_embed_cnt_info *cnt,
+ struct mbuf *m, int increment);
static int ng_source_dup_mod(sc_p, struct mbuf *,
struct mbuf **);
@@ -145,6 +150,14 @@ static const struct ng_parse_type ng_source_embed_type = {
&ng_source_embed_type_fields
};
+/* Parse type for struct ng_source_embed_cnt_info */
+static const struct ng_parse_struct_field ng_source_embed_cnt_type_fields[] =
+ NG_SOURCE_EMBED_CNT_TYPE_INFO;
+static const struct ng_parse_type ng_source_embed_cnt_type = {
+ &ng_parse_struct_type,
+ &ng_source_embed_cnt_type_fields
+};
+
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_source_cmds[] = {
{
@@ -217,6 +230,20 @@ static const struct ng_cmdlist ng_source_cmds[] = {
NULL,
&ng_source_embed_type
},
+ {
+ NGM_SOURCE_COOKIE,
+ NGM_SOURCE_SET_COUNTER,
+ "setcounter",
+ &ng_source_embed_cnt_type,
+ NULL
+ },
+ {
+ NGM_SOURCE_COOKIE,
+ NGM_SOURCE_GET_COUNTER,
+ "getcounter",
+ &ng_parse_uint8_type,
+ &ng_source_embed_cnt_type
+ },
{ 0 }
};
@@ -426,6 +453,41 @@ ng_source_rcvmsg(node_p node, item_p item, hook_p lasthook)
break;
}
+ case NGM_SOURCE_SET_COUNTER:
+ {
+ struct ng_source_embed_cnt_info *embed;
+
+ embed = (struct ng_source_embed_cnt_info *)msg->data;
+ if (embed->index >= NG_SOURCE_COUNTERS ||
+ !(embed->width == 1 || embed->width == 2 ||
+ embed->width == 4)) {
+ error = EINVAL;
+ goto done;
+ }
+ bcopy(embed, &sc->embed_counter[embed->index],
+ sizeof(*embed));
+
+ break;
+ }
+ case NGM_SOURCE_GET_COUNTER:
+ {
+ uint8_t index = *(uint8_t *)msg->data;
+ struct ng_source_embed_cnt_info *embed;
+
+ if (index >= NG_SOURCE_COUNTERS) {
+ error = EINVAL;
+ goto done;
+ }
+ NG_MKRESPONSE(resp, msg, sizeof(*embed), M_DONTWAIT);
+ if (resp == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+ embed = (struct ng_source_embed_cnt_info *)resp->data;
+ bcopy(&sc->embed_counter[index], embed, sizeof(*embed));
+
+ break;
+ }
default:
error = EINVAL;
break;
@@ -495,6 +557,7 @@ ng_source_rcvdata(hook_p hook, item_p item)
/* XXX should we check IF_QFULL() ? */
_IF_ENQUEUE(&sc->snd_queue, m);
sc->queueOctets += m->m_pkthdr.len;
+ sc->last_packet = m;
return (0);
}
@@ -600,6 +663,7 @@ ng_source_clr_data (sc_p sc)
NG_FREE_M(m);
}
sc->queueOctets = 0;
+ sc->last_packet = 0;
}
/*
@@ -761,16 +825,48 @@ ng_source_packet_mod(sc_p sc, struct mbuf *m, int offset, int len, caddr_t cp,
bcopy(cp, mtod_off(m, offset, caddr_t), len);
}
+static void
+ng_source_mod_counter(sc_p sc, struct ng_source_embed_cnt_info *cnt,
+ struct mbuf *m, int increment)
+{
+ caddr_t cp;
+ uint32_t val;
+
+ val = htonl(cnt->next_val);
+ cp = (caddr_t)&val + sizeof(val) - cnt->width;
+ ng_source_packet_mod(sc, m, cnt->offset, cnt->width, cp, cnt->flags);
+
+ if (increment) {
+ cnt->next_val += increment;
+
+ if (increment > 0 && cnt->next_val > cnt->max_val) {
+ cnt->next_val = cnt->min_val - 1 +
+ (cnt->next_val - cnt->max_val);
+ if (cnt->next_val > cnt->max_val)
+ cnt->next_val = cnt->max_val;
+ } else if (increment < 0 && cnt->next_val < cnt->min_val) {
+ cnt->next_val = cnt->max_val + 1 +
+ (cnt->next_val - cnt->min_val);
+ if (cnt->next_val < cnt->min_val)
+ cnt->next_val = cnt->max_val;
+ }
+ }
+}
+
static int
ng_source_dup_mod(sc_p sc, struct mbuf *m0, struct mbuf **m_ptr)
{
struct mbuf *m;
+ struct ng_source_embed_cnt_info *cnt;
struct ng_source_embed_info *ts;
int modify;
int error = 0;
+ int i, increment;
/* Are we going to modify packets? */
modify = sc->embed_timestamp.flags & NGM_SOURCE_EMBED_ENABLE;
+ for (i = 0; !modify && i < NG_SOURCE_COUNTERS; ++i)
+ modify = sc->embed_counter[i].flags & NGM_SOURCE_EMBED_ENABLE;
/* Duplicate the packet. */
if (modify)
@@ -789,6 +885,18 @@ ng_source_dup_mod(sc_p sc, struct mbuf *m0, struct mbuf **m_ptr)
/* Modify the copied packet for sending. */
KASSERT(M_WRITABLE(m), ("%s: packet not writable", __func__));
+ for (i = 0; i < NG_SOURCE_COUNTERS; ++i) {
+ cnt = &sc->embed_counter[i];
+ if (cnt->flags & NGM_SOURCE_EMBED_ENABLE) {
+ if ((cnt->flags & NGM_SOURCE_INC_CNT_PER_LIST) == 0 ||
+ sc->last_packet == m0)
+ increment = cnt->increment;
+ else
+ increment = 0;
+ ng_source_mod_counter(sc, cnt, m, increment);
+ }
+ }
+
ts = &sc->embed_timestamp;
if (ts->flags & NGM_SOURCE_EMBED_ENABLE) {
struct timeval now;
OpenPOWER on IntegriCloud