#include "qemu/osdep.h"
#include "trace.h"
#include "colo.h"
+#include "util.h"
uint32_t connection_key_hash(const void *opaque)
{
{
int network_length;
static const uint8_t vlan[] = {0x81, 0x00};
- uint8_t *data = pkt->data + pkt->vnet_hdr_len;
+ uint8_t *data = pkt->data;
uint16_t l3_proto;
- ssize_t l2hdr_len = eth_get_l2_hdr_length(data);
-
- if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) {
- trace_colo_proxy_main("pkt->size < ETH_HLEN");
+ ssize_t l2hdr_len;
+
+ assert(data);
+
+ /* Check the received vnet_hdr_len then add the offset */
+ if ((pkt->vnet_hdr_len > sizeof(struct virtio_net_hdr_v1_hash)) ||
+ (pkt->size < sizeof(struct eth_header) + sizeof(struct vlan_header) +
+ pkt->vnet_hdr_len)) {
+ /*
+ * The received remote packet maybe misconfiguration here,
+ * Please enable/disable filter module's the vnet_hdr flag at
+ * the same time.
+ */
+ trace_colo_proxy_main_vnet_info("This received packet load wrong ",
+ pkt->vnet_hdr_len, pkt->size);
return 1;
}
+ data += pkt->vnet_hdr_len;
+
+ l2hdr_len = eth_get_l2_hdr_length(data);
/*
* TODO: support vlan.
return 0;
}
-void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, Packet *pkt)
+void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key,
+ Packet *pkt, bool reverse)
{
+ if (reverse) {
+ key->src = pkt->ip->ip_dst;
+ key->dst = pkt->ip->ip_src;
+ key->src_port = ntohs(tmp_ports & 0xffff);
+ key->dst_port = ntohs(tmp_ports >> 16);
+ } else {
key->src = pkt->ip->ip_src;
key->dst = pkt->ip->ip_dst;
key->src_port = ntohs(tmp_ports >> 16);
key->dst_port = ntohs(tmp_ports & 0xffff);
+ }
}
-void fill_connection_key(Packet *pkt, ConnectionKey *key)
+void fill_connection_key(Packet *pkt, ConnectionKey *key, bool reverse)
{
- uint32_t tmp_ports;
+ uint32_t tmp_ports = 0;
- memset(key, 0, sizeof(*key));
key->ip_proto = pkt->ip->ip_p;
switch (key->ip_proto) {
case IPPROTO_SCTP:
case IPPROTO_UDPLITE:
tmp_ports = *(uint32_t *)(pkt->transport_header);
- extract_ip_and_port(tmp_ports, key, pkt);
break;
case IPPROTO_AH:
tmp_ports = *(uint32_t *)(pkt->transport_header + 4);
- extract_ip_and_port(tmp_ports, key, pkt);
break;
default:
break;
}
-}
-void reverse_connection_key(ConnectionKey *key)
-{
- struct in_addr tmp_ip;
- uint16_t tmp_port;
-
- tmp_ip = key->src;
- key->src = key->dst;
- key->dst = tmp_ip;
-
- tmp_port = key->src_port;
- key->src_port = key->dst_port;
- key->dst_port = tmp_port;
+ extract_ip_and_port(tmp_ports, key, pkt, reverse);
}
Connection *connection_new(ConnectionKey *key)
{
- Connection *conn = g_slice_new(Connection);
+ Connection *conn = g_slice_new0(Connection);
conn->ip_proto = key->ip_proto;
conn->processing = false;
- conn->offset = 0;
- conn->syn_flag = 0;
- conn->pack = 0;
- conn->sack = 0;
+ conn->tcp_state = TCPS_CLOSED;
g_queue_init(&conn->primary_list);
g_queue_init(&conn->secondary_list);
Packet *packet_new(const void *data, int size, int vnet_hdr_len)
{
- Packet *pkt = g_slice_new(Packet);
+ Packet *pkt = g_slice_new0(Packet);
pkt->data = g_memdup(data, size);
pkt->size = size;
pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
pkt->vnet_hdr_len = vnet_hdr_len;
- pkt->tcp_seq = 0;
- pkt->tcp_ack = 0;
- pkt->seq_end = 0;
- pkt->header_size = 0;
- pkt->payload_size = 0;
- pkt->offset = 0;
- pkt->flags = 0;
+
+ return pkt;
+}
+
+/*
+ * packet_new_nocopy will not copy data, so the caller can't release
+ * the data. And it will be released in packet_destroy.
+ */
+Packet *packet_new_nocopy(void *data, int size, int vnet_hdr_len)
+{
+ Packet *pkt = g_slice_new0(Packet);
+
+ pkt->data = data;
+ pkt->size = size;
+ pkt->creation_ms = qemu_clock_get_ms(QEMU_CLOCK_HOST);
+ pkt->vnet_hdr_len = vnet_hdr_len;
return pkt;
}
g_slice_free(Packet, pkt);
}
+void packet_destroy_partial(void *opaque, void *user_data)
+{
+ Packet *pkt = opaque;
+
+ g_slice_free(Packet, pkt);
+}
+
/*
* Clear hashtable, stop this hash growing really huge
*/
/*
* clear the conn_list
*/
- while (!g_queue_is_empty(conn_list)) {
+ while (conn_list && !g_queue_is_empty(conn_list)) {
connection_destroy(g_queue_pop_head(conn_list));
}
}
return conn;
}
+
+bool connection_has_tracked(GHashTable *connection_track_table,
+ ConnectionKey *key)
+{
+ Connection *conn = g_hash_table_lookup(connection_track_table, key);
+
+ return conn ? true : false;
+}