Example #1
0
/* Executes set nw dst action. */
static void
set_nw_dst(struct packet *pkt, struct ofl_action_nw_addr *act) {
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->proto->ipv4 != NULL) {
        struct ip_header *ipv4 = pkt->handle_std->proto->ipv4;

        // update TCP/UDP checksum
        if (pkt->handle_std->proto->tcp != NULL) {
            struct tcp_header *tcp = pkt->handle_std->proto->tcp;

            tcp->tcp_csum = recalc_csum32(tcp->tcp_csum, ipv4->ip_dst, act->nw_addr);
        } else if (pkt->handle_std->proto->udp != NULL) {
            struct udp_header *udp = pkt->handle_std->proto->udp;

            udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_dst, act->nw_addr);
        }

        ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_dst, act->nw_addr);
        ipv4->ip_dst = act->nw_addr;

        pkt->handle_std->match->nw_dst = act->nw_addr;
    } else {
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_NW_DST action on packet with no nw.");
    }
}
Example #2
0
static void
packet_set_ipv4_addr(struct ofpbuf *packet, ovs_be32 *addr, ovs_be32 new_addr)
{
    struct ip_header *nh = packet->l3;

    if (nh->ip_proto == IPPROTO_TCP && packet->l7) {
        struct tcp_header *th = packet->l4;

        th->tcp_csum = recalc_csum32(th->tcp_csum, *addr, new_addr);
    } else if (nh->ip_proto == IPPROTO_UDP && packet->l7) {
        struct udp_header *uh = packet->l4;

        if (uh->udp_csum) {
            uh->udp_csum = recalc_csum32(uh->udp_csum, *addr, new_addr);
            if (!uh->udp_csum) {
                uh->udp_csum = htons(0xffff);
            }
        }
    }
    nh->ip_csum = recalc_csum32(nh->ip_csum, *addr, new_addr);
    *addr = new_addr;
}
static void
set_field(struct packet *pkt, struct ofl_action_set_field *act )
{
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->valid)
    {
        /*Field existence is guaranteed by the
        field pre-requisite on matching */
        switch(act->field->header) {
        case OXM_OF_ETH_DST: {
            memcpy(pkt->handle_std->proto->eth->eth_dst,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ETH_SRC: {
            memcpy(pkt->handle_std->proto->eth->eth_src,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ETH_TYPE: {
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            memcpy(&pkt->handle_std->proto->eth->eth_type,
                   v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_VLAN_VID: {
            struct vlan_header *vlan =  pkt->handle_std->proto->vlan;
            /* VLAN existence is no guaranteed by match prerquisite*/
            if(vlan != NULL) {
                uint16_t v = (*(uint16_t*)act->field->value);
                vlan->vlan_tci = htons((ntohs(vlan->vlan_tci) & ~VLAN_VID_MASK)
                                       | (v & VLAN_VID_MASK));

            }
            break;
        }
        case OXM_OF_VLAN_PCP: {
            struct vlan_header *vlan = pkt->handle_std->proto->vlan;
            /* VLAN existence is no guaranteed by match prerquisite*/
            if(vlan != NULL) {
                vlan->vlan_tci = (vlan->vlan_tci & ~htons(VLAN_PCP_MASK))
                                 | htons(*act->field->value << VLAN_PCP_SHIFT);
                break;
            }
        }
        case OXM_OF_IP_DSCP: {
            struct ip_header *ipv4 =  pkt->handle_std->proto->ipv4;
            uint8_t tos = (ipv4->ip_tos & ~IP_DSCP_MASK) |
                          (*act->field->value << 2);

            ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, (uint16_t)
                                          (ipv4->ip_tos), (uint16_t)tos);
            ipv4->ip_tos = tos;
            break;
        }
        case OXM_OF_IP_ECN: {
            struct ip_header *ipv4 =  pkt->handle_std->proto->ipv4;
            uint8_t tos = (ipv4->ip_tos & ~IP_ECN_MASK) |
                          (*act->field->value & IP_ECN_MASK);
            ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, (uint16_t)
                                          (ipv4->ip_tos), (uint16_t)tos);
            ipv4->ip_tos = tos;
            break;
        }
        case OXM_OF_IP_PROTO: {
            pkt->handle_std->proto->ipv4->ip_proto = *act->field->value;
            break;
        }
        case OXM_OF_IPV4_SRC: {
            struct ip_header *ipv4 = pkt->handle_std->proto->ipv4;

            /*Reconstruct TCP or UDP checksum*/
            if (pkt->handle_std->proto->tcp != NULL) {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum32(tcp->tcp_csum,
                                              ipv4->ip_src, *((uint32_t*) act->field->value));
            } else if (pkt->handle_std->proto->udp != NULL) {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum32(udp->udp_csum,
                                              ipv4->ip_src, *((uint32_t*) act->field->value));
            }

            ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_src,
                                          *((uint32_t*) act->field->value));

            ipv4->ip_src = *((uint32_t*) act->field->value);
            break;
        }
        case OXM_OF_IPV4_DST: {
            struct ip_header *ipv4 = pkt->handle_std->proto->ipv4;

            /*Reconstruct TCP or UDP checksum*/
            if (pkt->handle_std->proto->tcp != NULL) {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum32(tcp->tcp_csum,
                                              ipv4->ip_dst, *((uint32_t*) act->field->value));
            } else if (pkt->handle_std->proto->udp != NULL) {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum32(udp->udp_csum,
                                              ipv4->ip_dst, *((uint32_t*) act->field->value));
            }

            ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_dst,
                                          *((uint32_t*) act->field->value));

            ipv4->ip_dst = *((uint32_t*) act->field->value);
            break;
        }
        case OXM_OF_TCP_SRC: {
            struct tcp_header *tcp = pkt->handle_std->proto->tcp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_src,*v);
            memcpy(&tcp->tcp_src, v, OXM_LENGTH(act->field->header));

            break;
        }
        case OXM_OF_TCP_DST: {
            struct tcp_header *tcp = pkt->handle_std->proto->tcp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_dst,*v);
            memcpy(&tcp->tcp_dst, v, OXM_LENGTH(act->field->header));

            break;
        }
        case OXM_OF_UDP_SRC: {
            struct udp_header *udp = pkt->handle_std->proto->udp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, *v);
            memcpy(&udp->udp_src, v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_UDP_DST: {
            struct udp_header *udp = pkt->handle_std->proto->udp;
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, *v);
            memcpy(&udp->udp_dst, v, OXM_LENGTH(act->field->header));
            break;
        }
        /*TODO recalculate SCTP checksum*/
        case OXM_OF_SCTP_SRC: {
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            memcpy(&pkt->handle_std->proto->sctp->sctp_src,
                   v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_SCTP_DST: {
            uint16_t *v = (uint16_t*) act->field->value;
            *v = htons(*v);
            memcpy(&pkt->handle_std->proto->sctp->sctp_dst,
                   v, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ICMPV4_TYPE:
        case OXM_OF_ICMPV6_TYPE: {
            pkt->handle_std->proto->icmp->icmp_type = *act->field->value;
            break;
        }

        case OXM_OF_ICMPV4_CODE:
        case OXM_OF_ICMPV6_CODE: {
            pkt->handle_std->proto->icmp->icmp_code = *act->field->value;
            break;
        }
        case OXM_OF_ARP_OP: {
            pkt->handle_std->proto->arp->ar_op = htons(*((uint16_t*) act->field->value));
            break;
        }
        case OXM_OF_ARP_SPA: {
            pkt->handle_std->proto->arp->ar_spa = *((uint32_t*)
                                                    act->field->value);
            break;
        }
        case OXM_OF_ARP_TPA: {
            pkt->handle_std->proto->arp->ar_tpa = *((uint32_t*)
                                                    act->field->value);
            break;
        }
        case OXM_OF_ARP_SHA: {
            memcpy(pkt->handle_std->proto->arp->ar_sha,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_ARP_THA: {
            memcpy(pkt->handle_std->proto->arp->ar_tha,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_SRC: {
            memcpy(&pkt->handle_std->proto->ipv6->ipv6_src,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_DST: {
            memcpy(&pkt->handle_std->proto->ipv6->ipv6_dst,
                   act->field->value, OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_FLABEL: {
            struct ipv6_header *ipv6 = (struct ipv6_header*)
                                       pkt->handle_std->proto->ipv6;
            uint32_t v = *((uint32_t*) act->field->value);
            ipv6->ipv6_ver_tc_fl  = (ipv6->ipv6_ver_tc_fl  &
                                     ~ntohl(IPV6_FLABEL_MASK)) | ntohl(v & IPV6_FLABEL_MASK);
            break;
        }
        /*IPV6 Neighbor Discovery */
        case OXM_OF_IPV6_ND_TARGET: {
            struct icmp_header *icmp = pkt->handle_std->proto->icmp;
            uint8_t offset;
            uint8_t *data = (uint8_t*)icmp;
            /*ICMP header + neighbor discovery header reserverd bytes*/
            offset = sizeof(struct icmp_header) + 4;

            memcpy(data + offset, act->field->value,
                   OXM_LENGTH(act->field->header));
            break;
        }
        case OXM_OF_IPV6_ND_SLL: {
            struct icmp_header *icmp = pkt->handle_std->proto->icmp;
            uint8_t offset;
            struct ipv6_nd_options_hd *opt = (struct ipv6_nd_options_hd*)
                                             icmp + sizeof(struct icmp_header);
            uint8_t *data = (uint8_t*) opt;
            /*ICMP header + neighbor discovery header reserverd bytes*/
            offset = sizeof(struct ipv6_nd_header);

            if(opt->type == ND_OPT_SLL) {
                memcpy(data + offset, act->field->value,
                       OXM_LENGTH(act->field->header));
            }
            break;
        }
        case OXM_OF_IPV6_ND_TLL: {
            struct icmp_header *icmp = pkt->handle_std->proto->icmp;
            uint8_t offset;
            struct ipv6_nd_options_hd *opt = (struct ipv6_nd_options_hd*)
                                             icmp + sizeof(struct icmp_header);
            uint8_t *data = (uint8_t*) opt;
            /*ICMP header + neighbor discovery header reserverd bytes*/
            offset = sizeof(struct ipv6_nd_header);

            if(opt->type == ND_OPT_TLL) {
                memcpy(data + offset, act->field->value,
                       OXM_LENGTH(act->field->header));
            }
            break;
        }
        case OXM_OF_MPLS_LABEL: {
            struct mpls_header *mpls = pkt->handle_std->proto->mpls;
            uint32_t v = *((uint32_t*) act->field->value);
            mpls->fields = (mpls->fields & ~ntohl(MPLS_LABEL_MASK)) |
                           ntohl((v << MPLS_LABEL_SHIFT) & MPLS_LABEL_MASK);
            break;
        }
        case OXM_OF_MPLS_TC: {
            struct mpls_header *mpls = pkt->handle_std->proto->mpls;
            mpls->fields = (mpls->fields & ~ntohl(MPLS_TC_MASK))
                           | ntohl((*act->field->value << MPLS_TC_SHIFT) & MPLS_TC_MASK);
            break;
        }
        case OXM_OF_MPLS_BOS: {
            struct mpls_header *mpls = pkt->handle_std->proto->mpls;
            mpls->fields = (mpls->fields & ~ntohl(MPLS_S_MASK))
                           | ntohl((*act->field->value << MPLS_S_SHIFT) & MPLS_S_MASK);
            break;
        }
        case OXM_OF_PBB_ISID : {
            struct pbb_header *pbb = pkt->handle_std->proto->pbb;
            uint32_t v = *((uint32_t*) act->field->value);
            pbb->id = (pbb->id & ~ntohl(PBB_ISID_MASK)) |
                      ntohl(v & PBB_ISID_MASK);
            break;
        }
        default:
            VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to set unknow field.");
            break;
        }
        pkt->handle_std->valid = false;
        return;
    }

}
Example #4
0
int
main(void)
{
    const struct test_case *tc;
    int i;

    for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
        const uint16_t *data16 = (const uint16_t *) tc->data;
        const uint32_t *data32 = (const uint32_t *) tc->data;
        uint32_t partial;
        size_t i;

        /* Test csum(). */
        assert(ntohs(csum(tc->data, tc->size)) == tc->csum);
        mark('.');

        /* Test csum_add16(). */
        partial = 0;
        for (i = 0; i < tc->size / 2; i++) {
            partial = csum_add16(partial, data16[i]);
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('.');

        /* Test csum_add32(). */
        partial = 0;
        for (i = 0; i < tc->size / 4; i++) {
            partial = csum_add32(partial, data32[i]);
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('.');

        /* Test alternating csum_add16() and csum_add32(). */
        partial = 0;
        for (i = 0; i < tc->size / 4; i++) {
            if (i % 2) {
                partial = csum_add32(partial, data32[i]);
            } else {
                partial = csum_add16(partial, data16[i * 2]);
                partial = csum_add16(partial, data16[i * 2 + 1]);
            }
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('.');

        /* Test csum_continue(). */
        partial = 0;
        for (i = 0; i < tc->size / 4; i++) {
            if (i) {
                partial = csum_continue(partial, &data32[i], 4);
            } else {
                partial = csum_continue(partial, &data16[i * 2], 2);
                partial = csum_continue(partial, &data16[i * 2 + 1], 2);
            }
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('#');
    }

    test_rfc1624();

    /* Test recalc_csum16(). */
    for (i = 0; i < 32; i++) {
        uint16_t old_u16, new_u16;
        uint16_t old_csum;
        uint16_t data[16];
        int j, index;

        for (j = 0; j < ARRAY_SIZE(data); j++) {
            data[j] = random_uint32();
        }
        old_csum = csum(data, sizeof data);
        index = random_range(ARRAY_SIZE(data));
        old_u16 = data[index];
        new_u16 = data[index] = random_uint32();
        assert(csum(data, sizeof data)
               == recalc_csum16(old_csum, old_u16, new_u16));
        mark('.');
    }
    mark('#');

    /* Test recalc_csum32(). */
    for (i = 0; i < 32; i++) {
        uint32_t old_u32, new_u32;
        uint16_t old_csum;
        uint32_t data[16];
        int j, index;

        for (j = 0; j < ARRAY_SIZE(data); j++) {
            data[j] = random_uint32();
        }
        old_csum = csum(data, sizeof data);
        index = random_range(ARRAY_SIZE(data));
        old_u32 = data[index];
        new_u32 = data[index] = random_uint32();
        assert(csum(data, sizeof data)
               == recalc_csum32(old_csum, old_u32, new_u32));
        mark('.');
    }
    mark('#');

    putchar('\n');

    return 0;
}
Example #5
0
static void
set_field(struct packet *pkt, struct ofl_action_set_field *act ) 
{
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->valid)
    {
        struct packet_fields *iter;
        /* Search field on the description of the packet. */
        HMAP_FOR_EACH_WITH_HASH(iter,struct packet_fields, hmap_node, hash_int(act->field->header,0), &pkt->handle_std->match.match_fields)
        {
            /* TODO: Checksum for SCTP and ICMP */
            if (iter->header == OXM_OF_IPV4_SRC || iter->header == OXM_OF_IPV4_DST 
                || iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
            {
                uint16_t *aux_old ;
                aux_old = (uint16_t *)malloc(sizeof(uint16_t));
                memcpy(aux_old, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                if (iter->header == OXM_OF_IP_DSCP)
                {
                    uint8_t* aux;
                    aux = (uint8_t *)malloc(OXM_LENGTH(iter->header));
                    memcpy(aux,((uint8_t*)pkt->buffer->data + iter->pos) , OXM_LENGTH(iter->header));
                    *aux = *aux ^ ((*act->field->value) << 2 );
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , aux , OXM_LENGTH(iter->header));
                    free(aux);
                }
                else if (iter->header == OXM_OF_IP_ECN)
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }
                else 
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }
                
                // update TCP/UDP checksum
                struct ip_header *ipv4 = pkt->handle_std->proto->ipv4;
                if (pkt->handle_std->proto->tcp != NULL) {
                    struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_src,htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_dst,htonl(*((uint32_t*) act->field->value)));
                    }
                } else if (pkt->handle_std->proto->udp != NULL) {
                    struct udp_header *udp = pkt->handle_std->proto->udp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                    }
                }
                if (iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
                {
                    uint16_t *aux ;
                    aux = (uint16_t *)malloc(sizeof(uint16_t));
                    memcpy(aux, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                    ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, *aux_old, *aux);
                    free(aux);
                }
                else if (iter->header == OXM_OF_IPV4_SRC)
                {
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                }
                else 
                { 
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                }  
                pkt->handle_std->valid = false;
                packet_handle_std_validate(pkt->handle_std);
                free(aux_old);
                return;        	       
            }
            if (iter->header == OXM_OF_TCP_SRC)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_TCP_DST)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_dst, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_SRC)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_DST)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, htons(*((uint16_t*) act->field->value)));
            }
            if (iter->header == OXM_OF_IPV6_SRC || iter->header == OXM_OF_IPV6_DST || 
                iter->header == OXM_OF_ETH_SRC || iter->header == OXM_OF_ETH_DST   ||
                iter->header == OXM_OF_ARP_SPA || iter->header == OXM_OF_ARP_TPA   ||
                iter->header == OXM_OF_ARP_SHA || iter->header == OXM_OF_ARP_THA)
            {
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }
            /* Found the field, lets re-write it!! */
    	    uint8_t* tmp = (uint8_t*) malloc(OXM_LENGTH(iter->header));
    	    uint8_t i;
    	    for (i=0;i<OXM_LENGTH(iter->header);i++)
    	    {
        	    memcpy(((uint8_t*)tmp + i) , (act->field->value + OXM_LENGTH(iter->header) - i -1 ), 1); 
    	    }  
    	    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , tmp , OXM_LENGTH(iter->header));
            pkt->handle_std->valid = false;
    	    return;
        }
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_FIELD action on packet with no corresponding field.");
    }

}
Example #6
0
int
main(void)
{
    const struct test_case *tc;
    int i;

    for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
        const void *data = tc->data;
        const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) data;
        const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) data;
        uint32_t partial;

        /* Test csum(). */
        assert(ntohs(csum(tc->data, tc->size)) == tc->csum);
        mark('.');

        /* Test csum_add16(). */
        partial = 0;
        for (i = 0; i < tc->size / 2; i++) {
            partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('.');

        /* Test csum_add32(). */
        partial = 0;
        for (i = 0; i < tc->size / 4; i++) {
            partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('.');

        /* Test alternating csum_add16() and csum_add32(). */
        partial = 0;
        for (i = 0; i < tc->size / 4; i++) {
            if (i % 2) {
                partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
            } else {
                ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
                ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
                partial = csum_add16(partial, u0);
                partial = csum_add16(partial, u1);
            }
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('.');

        /* Test csum_continue(). */
        partial = 0;
        for (i = 0; i < tc->size / 4; i++) {
            if (i) {
                partial = csum_continue(partial, &data32[i], 4);
            } else {
                partial = csum_continue(partial, &data16[i * 2], 2);
                partial = csum_continue(partial, &data16[i * 2 + 1], 2);
            }
        }
        assert(ntohs(csum_finish(partial)) == tc->csum);
        mark('#');
    }

    test_rfc1624();

    /* Test recalc_csum16(). */
    for (i = 0; i < 32; i++) {
        ovs_be16 old_u16, new_u16;
        ovs_be16 old_csum;
        ovs_be16 data[16];
        int j, index;

        for (j = 0; j < ARRAY_SIZE(data); j++) {
            data[j] = (OVS_FORCE ovs_be16) random_uint32();
        }
        old_csum = csum(data, sizeof data);
        index = random_range(ARRAY_SIZE(data));
        old_u16 = data[index];
        new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
        assert(csum(data, sizeof data)
               == recalc_csum16(old_csum, old_u16, new_u16));
        mark('.');
    }
    mark('#');

    /* Test recalc_csum32(). */
    for (i = 0; i < 32; i++) {
        ovs_be32 old_u32, new_u32;
        ovs_be16 old_csum;
        ovs_be32 data[16];
        int j, index;

        for (j = 0; j < ARRAY_SIZE(data); j++) {
            data[j] = (OVS_FORCE ovs_be32) random_uint32();
        }
        old_csum = csum(data, sizeof data);
        index = random_range(ARRAY_SIZE(data));
        old_u32 = data[index];
        new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
        assert(csum(data, sizeof data)
               == recalc_csum32(old_csum, old_u32, new_u32));
        mark('.');
    }
    mark('#');

    putchar('\n');

    return 0;
}
static void
set_field(struct packet *pkt, struct ofl_action_set_field *act ) 
{
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->valid)
    {
        struct packet_fields *iter;
        /* Search field on the description of the packet. */
        HMAP_FOR_EACH_WITH_HASH(iter,struct packet_fields, hmap_node, hash_int(act->field->header,0), &pkt->handle_std->match.match_fields)
        {
            struct ip_header *ipv4;
            struct mpls_header *mpls;
            struct vlan_header *vlan;
            uint8_t* tmp;
            size_t i;
            
            /* TODO: Checksum for SCTP and ICMP */
            if (iter->header == OXM_OF_IPV4_SRC || iter->header == OXM_OF_IPV4_DST 
                || iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
            {
                uint16_t *aux_old ;
                aux_old = (uint16_t *)malloc(sizeof(uint16_t));
                memcpy(aux_old, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                if (iter->header == OXM_OF_IP_DSCP)
                {
                    uint8_t* aux;
                    aux = (uint8_t *)malloc(OXM_LENGTH(iter->header));
                    memcpy(aux,((uint8_t*)pkt->buffer->data + iter->pos) , OXM_LENGTH(iter->header));
                    *aux = *aux ^ ((*act->field->value) << 2 );
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , aux , OXM_LENGTH(iter->header));
                    free(aux);
                }
                else if (iter->header == OXM_OF_IP_ECN)
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }
                else 
                {
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                }

                // update TCP/UDP checksum
                ipv4 = pkt->handle_std->proto->ipv4;
                if (pkt->handle_std->proto->tcp != NULL) {
                    struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_src,htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, ipv4->ip_dst,htonl(*((uint32_t*) act->field->value)));
                    }
                } else if (pkt->handle_std->proto->udp != NULL) {
                    struct udp_header *udp = pkt->handle_std->proto->udp;
                    if (iter->header == OXM_OF_IPV4_SRC)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                    }
                    else if (iter->header == OXM_OF_IPV4_DST)
                    {
                        udp->udp_csum = recalc_csum32(udp->udp_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                    }
                }

                if (iter->header == OXM_OF_IP_DSCP || iter->header == OXM_OF_IP_ECN)
                {
                    uint16_t *aux ;
                    aux = (uint16_t *)malloc(sizeof(uint16_t));
                    memcpy(aux, ((uint8_t*)pkt->buffer->data + iter->pos - 1) , (2 * OXM_LENGTH(iter->header)));
                    ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, *aux_old, *aux);
                    free(aux);
                }
                else if (iter->header == OXM_OF_IPV4_SRC)
                {
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_src, htonl(*((uint32_t*) act->field->value)));
                }
                else 
                { 
                    ipv4->ip_csum = recalc_csum32(ipv4->ip_csum, ipv4->ip_dst, htonl(*((uint32_t*) act->field->value)));
                }  
                pkt->handle_std->valid = false;
                packet_handle_std_validate(pkt->handle_std);
                free(aux_old);
                return;        	       
            }
            if (iter->header == OXM_OF_TCP_SRC)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_TCP_DST)
            {
                struct tcp_header *tcp = pkt->handle_std->proto->tcp;
                tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_dst, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_SRC)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_src, htons(*((uint16_t*) act->field->value)));
            }
            else if (iter->header == OXM_OF_UDP_DST)
            {
                struct udp_header *udp = pkt->handle_std->proto->udp;
                udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, htons(*((uint16_t*) act->field->value)));
            }
            if (iter->header == OXM_OF_IPV6_SRC || iter->header == OXM_OF_IPV6_DST || 
                iter->header == OXM_OF_ETH_SRC || iter->header == OXM_OF_ETH_DST   ||
                iter->header == OXM_OF_ARP_SPA || iter->header == OXM_OF_ARP_TPA   ||
                iter->header == OXM_OF_ARP_SHA || iter->header == OXM_OF_ARP_THA) {
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , act->field->value , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }
            if (iter->header == OXM_OF_VLAN_VID){
                uint16_t vlan_id =  *((uint16_t*) act->field->value);
                vlan = pkt->handle_std->proto->vlan;
                vlan->vlan_tci = htons((ntohs(vlan->vlan_tci) & ~VLAN_VID_MASK) | (vlan_id & VLAN_VID_MASK));
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &vlan->vlan_tci , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }            
            if (iter->header == OXM_OF_VLAN_PCP){
                uint8_t vlan_pcp =  *((uint8_t*) act->field->value);
                vlan = pkt->handle_std->proto->vlan;
                vlan->vlan_tci = htons((ntohs(vlan->vlan_tci) & ~VLAN_PCP_MASK) | ((vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK));
                memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &vlan->vlan_tci , OXM_LENGTH(iter->header));
                pkt->handle_std->valid = false;
                return;
            }
            if (iter->header == OXM_OF_MPLS_LABEL){
                    uint32_t mpls_label =  *((uint32_t*) act->field->value);
                    mpls = pkt->handle_std->proto->mpls;
                    mpls->fields = (mpls->fields & ~ntohl(MPLS_LABEL_MASK)) | ntohl((mpls_label << MPLS_LABEL_SHIFT) & MPLS_LABEL_MASK);
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &mpls->fields , OXM_LENGTH(iter->header));
                    pkt->handle_std->valid = false;
                    return;
            }
            if (iter->header == OXM_OF_MPLS_TC){
                    mpls = pkt->handle_std->proto->mpls;
                    mpls->fields = (mpls->fields & ~ntohl(MPLS_TC_MASK)) | ntohl((*act->field->value << MPLS_TC_SHIFT) & MPLS_TC_MASK);
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &mpls->fields , OXM_LENGTH(iter->header));
                    pkt->handle_std->valid = false;
                    return;
            }
            if (iter->header == OXM_OF_MPLS_BOS){
                    mpls = pkt->handle_std->proto->mpls;
                    mpls->fields = (mpls->fields & ~ntohl(MPLS_S_MASK)) | ntohl((*act->field->value << MPLS_S_SHIFT) & MPLS_S_MASK);
                    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , &mpls->fields , OXM_LENGTH(iter->header));
                    pkt->handle_std->valid = false;
                    return;             
            }
            tmp = (uint8_t*) malloc(OXM_LENGTH(iter->header));
    	    for (i=0;i<OXM_LENGTH(iter->header);i++)
    	    {
        	    memcpy(((uint8_t*)tmp + i) , (act->field->value + OXM_LENGTH(iter->header) - i -1 ), 1); 
    	    }
    	    memcpy(((uint8_t*)pkt->buffer->data + iter->pos) , tmp , OXM_LENGTH(iter->header));
            pkt->handle_std->valid = false;
    	    return;
        }
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_FIELD action on packet with no corresponding field.");
    }

}