// client options
static unsigned int client_options = 0;
+// counters for statistics
+static struct dhcpv6_stats dhcpv6_stats = {0};
+
static uint32_t ntohl_unaligned(const uint8_t *data)
{
uint32_t buf;
dhcpv6_reset_state_timeout();
}
+static void dhcpv6_inc_counter(enum dhcpv6_msg type)
+{
+ switch (type) {
+ case DHCPV6_MSG_SOLICIT:
+ dhcpv6_stats.solicit++;
+ break;
+
+ case DHCPV6_MSG_ADVERT:
+ dhcpv6_stats.advertise++;
+ break;
+
+ case DHCPV6_MSG_REQUEST:
+ dhcpv6_stats.request++;
+ break;
+
+ case DHCPV6_MSG_RENEW:
+ dhcpv6_stats.renew++;
+ break;
+
+ case DHCPV6_MSG_REBIND:
+ dhcpv6_stats.rebind++;
+ break;
+
+ case DHCPV6_MSG_REPLY:
+ dhcpv6_stats.reply++;
+ break;
+
+ case DHCPV6_MSG_RELEASE:
+ dhcpv6_stats.release++;
+ break;
+
+ case DHCPV6_MSG_DECLINE:
+ dhcpv6_stats.decline++;
+ break;
+
+ case DHCPV6_MSG_RECONF:
+ dhcpv6_stats.reconfigure++;
+ break;
+
+ case DHCPV6_MSG_INFO_REQ:
+ dhcpv6_stats.information_request++;
+ break;
+
+ default:
+ break;
+ }
+}
+
static char *dhcpv6_msg_to_str(enum dhcpv6_msg msg)
{
switch (msg) {
dhcpv6_state_timeout = 0;
}
+struct dhcpv6_stats dhcpv6_get_stats(void)
+{
+ return dhcpv6_stats;
+}
+
+void dhcpv6_reset_stats(void)
+{
+ memset(&dhcpv6_stats, 0, sizeof(dhcpv6_stats));
+}
+
int init_dhcpv6(const char *ifname, unsigned int options, int sk_prio, int sol_timeout, unsigned int dscp)
{
client_options = options;
dhcpv6_msg_to_str(type),
inet_ntop(AF_INET6, (const void *)&srv.sin6_addr,
in6_str, sizeof(in6_str)), strerror(errno));
+ dhcpv6_stats.transmit_failures++;
+ } else {
+ dhcpv6_inc_counter(type);
}
}
}
if (pktinfo == NULL) {
+ dhcpv6_stats.discarded_packets++;
return -1;
}
if (!dhcpv6_response_is_valid(buf, len, retx->tr_id, type,
&pktinfo->ipi6_addr)) {
+ dhcpv6_stats.discarded_packets++;
return -1;
}
+ dhcpv6_inc_counter(hdr->msg_type);
+
uint8_t *opt = &buf[4];
uint8_t *opt_end = opt + len - 4;
retx->round_start = odhcp6c_get_milli_time();
static int ubus_handle_get_state(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
+static int ubus_handle_get_stats(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg);
+static int ubus_handle_reset_stats(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg);
static struct ubus_method odhcp6c_object_methods[] = {
UBUS_METHOD_NOARG("get_state", ubus_handle_get_state),
+ UBUS_METHOD_NOARG("get_statistics", ubus_handle_get_stats),
+ UBUS_METHOD_NOARG("reset_statistics", ubus_handle_reset_stats),
};
static struct ubus_object_type odhcp6c_object_type =
return UBUS_STATUS_OK;
}
+static int ubus_handle_get_stats(struct ubus_context *ctx, _unused struct ubus_object *obj,
+ struct ubus_request_data *req, _unused const char *method,
+ _unused struct blob_attr *msg)
+{
+ struct dhcpv6_stats stats = dhcpv6_get_stats();
+
+ blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
+ blobmsg_add_u64(&b, "dhcp_solicit", stats.solicit);
+ blobmsg_add_u64(&b, "dhcp_advertise", stats.advertise);
+ blobmsg_add_u64(&b, "dhcp_request", stats.request);
+ blobmsg_add_u64(&b, "dhcp_confirm", stats.confirm);
+ blobmsg_add_u64(&b, "dhcp_renew", stats.renew);
+ blobmsg_add_u64(&b, "dhcp_rebind", stats.rebind);
+ blobmsg_add_u64(&b, "dhcp_reply", stats.reply);
+ blobmsg_add_u64(&b, "dhcp_release", stats.release);
+ blobmsg_add_u64(&b, "dhcp_decline", stats.decline);
+ blobmsg_add_u64(&b, "dhcp_reconfigure", stats.reconfigure);
+ blobmsg_add_u64(&b, "dhcp_information_request", stats.information_request);
+ blobmsg_add_u64(&b, "dhcp_discarded_packets", stats.discarded_packets);
+ blobmsg_add_u64(&b, "dhcp_transmit_failures", stats.transmit_failures);
+
+ CHECK(ubus_send_reply(ctx, req, b.head));
+ blob_buf_free(&b);
+
+ return UBUS_STATUS_OK;
+}
+
+static int ubus_handle_reset_stats(_unused struct ubus_context *ctx, _unused struct ubus_object *obj,
+ _unused struct ubus_request_data *req, _unused const char *method,
+ _unused struct blob_attr *msg)
+{
+ dhcpv6_reset_stats();
+
+ return UBUS_STATUS_OK;
+}
+
+
static int ubus_handle_get_state(struct ubus_context *ctx, _unused struct ubus_object *obj,
struct ubus_request_data *req, _unused const char *method,
_unused struct blob_attr *msg)