qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC PATCH v2 08/10] net/colo-proxy: Handle packet and


From: Dr. David Alan Gilbert
Subject: Re: [Qemu-devel] [RFC PATCH v2 08/10] net/colo-proxy: Handle packet and connection
Date: Fri, 19 Feb 2016 20:04:27 +0000
User-agent: Mutt/1.5.24 (2015-08-30)

* Zhang Chen (address@hidden) wrote:
> From: zhangchen <address@hidden>
> 
> In here we will handle ip packet and connection
> 
> Signed-off-by: zhangchen <address@hidden>
> Signed-off-by: zhanghailiang <address@hidden>
> ---
>  net/colo-proxy.c | 130 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 130 insertions(+)
> 
> diff --git a/net/colo-proxy.c b/net/colo-proxy.c
> index 5e5c72e..06bab80 100644
> --- a/net/colo-proxy.c
> +++ b/net/colo-proxy.c
> @@ -167,11 +167,141 @@ static int connection_key_equal(const void *opaque1, 
> const void *opaque2)
>      return memcmp(opaque1, opaque2, sizeof(ConnectionKey)) == 0;
>  }
>  
> +static void connection_destroy(void *opaque)
> +{
> +    Connection *conn = opaque;
> +
> +    g_queue_foreach(&conn->primary_list, packet_destroy, NULL);
> +    g_queue_free(&conn->primary_list);
> +    g_queue_foreach(&conn->secondary_list, packet_destroy, NULL);

Be careful about these lists and which threads access them;
I found I could occasionally trigger a seg fault as two
threads tried to manipulate them at once; I just put a 'list_lock'
in the connection, which seems to fix it, but I might have to be
more careful with deadlocks.

> +    g_queue_free(&conn->secondary_list);
> +    g_slice_free(Connection, conn);
> +}
> +
> +static Connection *connection_new(ConnectionKey *key)
> +{
> +    Connection *conn = g_slice_new(Connection);
> +
> +    conn->ip_proto = key->ip_proto;
> +    conn->processing = false;
> +    g_queue_init(&conn->primary_list);
> +    g_queue_init(&conn->secondary_list);
> +
> +    return conn;
> +}
> +
> +/*
> + * Clear hashtable, stop this hash growing really huge
> + */
> +static void clear_connection_hashtable(COLOProxyState *s)
> +{
> +    s->hashtable_size = 0;
> +    g_hash_table_remove_all(colo_conn_hash);
> +    trace_colo_proxy("clear_connection_hashtable");
> +}
> +
>  bool colo_proxy_query_checkpoint(void)
>  {
>      return colo_do_checkpoint;
>  }
>  
> +/* Return 0 on success, or return -1 if the pkt is corrupted */
> +static int parse_packet_early(Packet *pkt, ConnectionKey *key)
> +{
> +    int network_length;
> +    uint8_t *data = pkt->data;
> +    uint16_t l3_proto;
> +    uint32_t tmp_ports;
> +    ssize_t l2hdr_len = eth_get_l2_hdr_length(data);
> +
> +    pkt->network_layer = data + ETH_HLEN;
> +    l3_proto = eth_get_l3_proto(data, l2hdr_len);
> +    if (l3_proto != ETH_P_IP) {
> +        if (l3_proto == ETH_P_ARP) {
> +            return -1;
> +        }
> +        return 0;
> +    }
> +
> +    network_length = pkt->ip->ip_hl * 4;
> +    pkt->transport_layer = pkt->network_layer + network_length;
> +    key->ip_proto = pkt->ip->ip_p;
> +    key->src = pkt->ip->ip_src;
> +    key->dst = pkt->ip->ip_dst;
> +
> +    switch (key->ip_proto) {
> +    case IPPROTO_TCP:
> +    case IPPROTO_UDP:
> +    case IPPROTO_DCCP:
> +    case IPPROTO_ESP:
> +    case IPPROTO_SCTP:
> +    case IPPROTO_UDPLITE:
> +        tmp_ports = *(uint32_t *)(pkt->transport_layer);
> +        key->src_port = tmp_ports & 0xffff;
> +        key->dst_port = tmp_ports >> 16;

These fields are not byteswapped; it makes it very confusing
when printing them for debug;  I added htons around every
reading of the ports from the packets.

Dave

> +        break;
> +    case IPPROTO_AH:
> +        tmp_ports = *(uint32_t *)(pkt->transport_layer + 4);
> +        key->src_port = tmp_ports & 0xffff;
> +        key->dst_port = tmp_ports >> 16;
> +        break;
> +    default:
> +        break;
> +    }
> +
> +    return 0;
> +}
> +
> +static Packet *packet_new(COLOProxyState *s, void *data,
> +                          int size, ConnectionKey *key, NetClientState 
> *sender)
> +{
> +    Packet *pkt = g_slice_new(Packet);
> +
> +    pkt->data = data;
> +    pkt->size = size;
> +    pkt->s = s;
> +    pkt->sender = sender;
> +
> +    if (parse_packet_early(pkt, key)) {
> +        packet_destroy(pkt, NULL);
> +        pkt = NULL;
> +    }
> +
> +    return pkt;
> +}
> +
> +static void packet_destroy(void *opaque, void *user_data)
> +{
> +    Packet *pkt = opaque;
> +    g_free(pkt->data);
> +    g_slice_free(Packet, pkt);
> +}
> +
> +/* if not found, creata a new connection and add to hash table */
> +static Connection *colo_proxy_get_conn(COLOProxyState *s,
> +            ConnectionKey *key)
> +{
> +    /* FIXME: protect colo_conn_hash */
> +    Connection *conn = g_hash_table_lookup(colo_conn_hash, key);
> +
> +    if (conn == NULL) {
> +        ConnectionKey *new_key = g_malloc(sizeof(*key));
> +
> +        conn = connection_new(key);
> +        memcpy(new_key, key, sizeof(*key));
> +
> +        s->hashtable_size++;
> +        if (s->hashtable_size > hashtable_max_size) {
> +            trace_colo_proxy("colo proxy connection hashtable full, clear 
> it");
> +            clear_connection_hashtable(s);
> +        } else {
> +            g_hash_table_insert(colo_conn_hash, new_key, conn);
> +        }
> +    }
> +
> +     return conn;
> +}
> +
>  static ssize_t colo_proxy_enqueue_primary_packet(NetFilterState *nf,
>                                           NetClientState *sender,
>                                           unsigned flags,
> -- 
> 1.9.1
> 
> 
> 
> 
--
Dr. David Alan Gilbert / address@hidden / Manchester, UK



reply via email to

[Prev in Thread] Current Thread [Next in Thread]