static job_requeue_t process_inbound(private_ipsec_processor_t *this)
{
esp_packet_t *packet;
+ ip_packet_t *ip_packet;
ipsec_sa_t *sa;
u_int8_t next_header;
u_int32_t spi, reqid;
packet->destroy(packet);
return JOB_REQUEUE_DIRECT;
}
+ ip_packet = packet->get_payload(packet);
+ sa->update_usestats(sa, ip_packet->get_encoding(ip_packet).len);
reqid = sa->get_reqid(sa);
ipsec->sas->checkin(ipsec->sas, sa);
case IPPROTO_IPV6:
{
ipsec_policy_t *policy;
- ip_packet_t *ip_packet;
- ip_packet = packet->get_payload(packet);
policy = ipsec->policies->find_by_packet(ipsec->policies,
ip_packet, TRUE, reqid);
if (policy)
- { /* TODO-IPSEC: update policy/sa stats? */
+ {
deliver_inbound(this, packet);
policy->destroy(policy);
break;
policy->destroy(policy);
return JOB_REQUEUE_DIRECT;
}
- /* TODO-IPSEC: update policy/sa counters? */
+ sa->update_usestats(sa, packet->get_encoding(packet).len);
ipsec->sas->checkin(ipsec->sas, sa);
policy->destroy(policy);
send_outbound(this, esp_packet);
* ESP context
*/
esp_context_t *esp_context;
+
+ /**
+ * Usage statistics
+ */
+ struct {
+ /** last time of use */
+ time_t time;
+ /** number of packets processed */
+ u_int64_t packets;
+ /** number of bytes processed */
+ u_int64_t bytes;
+ } use;
};
METHOD(ipsec_sa_t, get_source, host_t*,
return this->esp_context;
}
+METHOD(ipsec_sa_t, get_usestats, void,
+ private_ipsec_sa_t *this, u_int64_t *bytes, u_int64_t *packets,
+ time_t *time)
+{
+ if (bytes)
+ {
+ *bytes = this->use.bytes;
+ }
+ if (packets)
+ {
+ *packets = this->use.packets;
+ }
+ if (time)
+ {
+ *time = this->use.time;
+ }
+}
+
+METHOD(ipsec_sa_t, update_usestats, void,
+ private_ipsec_sa_t *this, u_int32_t bytes)
+{
+ this->use.time = time_monotonic(NULL);
+ this->use.packets++;
+ this->use.bytes += bytes;
+}
+
METHOD(ipsec_sa_t, match_by_spi_dst, bool,
private_ipsec_sa_t *this, u_int32_t spi, host_t *dst)
{
.match_by_spi_src_dst = _match_by_spi_src_dst,
.match_by_reqid = _match_by_reqid,
.get_esp_context = _get_esp_context,
+ .get_usestats = _get_usestats,
+ .update_usestats = _update_usestats,
},
.spi = spi,
.src = src->clone(src),
*/
esp_context_t *(*get_esp_context)(ipsec_sa_t *this);
+ /**
+ * Get usage statistics for this SA.
+ *
+ * @param bytes receives number of processed bytes, or NULL
+ * @param packets receives number of processed packets, or NULL
+ * @param time receives last use time of this SA, or NULL
+ */
+ void (*get_usestats)(ipsec_sa_t *this, u_int64_t *bytes, u_int64_t *packets,
+ time_t *time);
+
+ /**
+ * Record en/decryption of a packet to update usage statistics.
+ *
+ * @param bytes length of packet processed
+ */
+ void (*update_usestats)(ipsec_sa_t *this, u_int32_t bytes);
+
/**
* Check if this SA matches all given parameters
*
return SUCCESS;
}
+METHOD(ipsec_sa_mgr_t, query_sa, status_t,
+ private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, u_int8_t protocol, mark_t mark,
+ u_int64_t *bytes, u_int64_t *packets, time_t *time)
+{
+ ipsec_sa_entry_t *entry = NULL;
+
+ this->mutex->lock(this->mutex);
+ if (this->sas->find_first(this->sas, (void*)match_entry_by_spi_src_dst,
+ (void**)&entry, &spi, src, dst) == SUCCESS &&
+ wait_for_entry(this, entry))
+ {
+ entry->sa->get_usestats(entry->sa, bytes, packets, time);
+ /* checkin the entry */
+ entry->locked = FALSE;
+ entry->condvar->signal(entry->condvar);
+ }
+ this->mutex->unlock(this->mutex);
+
+ return entry ? SUCCESS : NOT_FOUND;
+}
+
METHOD(ipsec_sa_mgr_t, del_sa, status_t,
private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, u_int32_t spi,
u_int8_t protocol, u_int16_t cpi, mark_t mark)
.get_spi = _get_spi,
.add_sa = _add_sa,
.update_sa = _update_sa,
+ .query_sa = _query_sa,
.del_sa = _del_sa,
.checkout_by_spi = _checkout_by_spi,
.checkout_by_reqid = _checkout_by_reqid,
host_t *new_src, host_t *new_dst,
bool encap, bool new_encap, mark_t mark);
+ /**
+ * Query the number of bytes processed by an SA from the SAD.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param mark optional mark for this SA
+ * @param[out] bytes the number of bytes processed by SA
+ * @param[out] packets number of packets processed by SA
+ * @param[out] time last (monotonic) time of SA use
+ * @return SUCCESS if operation completed
+ */
+ status_t (*query_sa)(ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, u_int8_t protocol, mark_t mark,
+ u_int64_t *bytes, u_int64_t *packets, time_t *time);
+
/**
* Delete a previously added SA
*