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
/* Executes set dl src action. */
static void
set_dl_src(struct packet *pkt, struct ofl_action_dl_addr *act) {
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->proto->eth != NULL) {
        struct eth_header *eth = pkt->handle_std->proto->eth;

        memcpy(eth->eth_src, act->dl_addr, ETH_ADDR_LEN);

        memcpy(&pkt->handle_std->match->dl_src, act->dl_addr, ETH_ADDR_LEN);
    } else {
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_DL_SRC action on packet with no dl.");
    }
}
Example #3
0
/* Executes set vlan pcp action. */
static void
set_vlan_pcp(struct packet *pkt, struct ofl_action_vlan_pcp *act) {
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->proto->vlan != NULL) {
        struct vlan_header *vlan = pkt->handle_std->proto->vlan;

        vlan->vlan_tci = (vlan->vlan_tci & ~htons(VLAN_PCP_MASK)) | htons(act->vlan_pcp << VLAN_PCP_SHIFT);

        pkt->handle_std->match->dl_vlan_pcp = act->vlan_pcp;
    } else {
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_VLAN_PCP action on packet with no vlan.");
    }
}
struct packet_handle_std *
packet_handle_std_create(struct packet *pkt) {
	struct packet_handle_std *handle = xmalloc(sizeof(struct packet_handle_std));
	handle->proto = xmalloc(sizeof(struct protocols_std));
	handle->pkt = pkt;

	hmap_init(&handle->match.match_fields);

	handle->valid = false;
	packet_handle_std_validate(handle);

	return handle;
}
Example #5
0
/* Executes a set vlan vid action. */
static void
set_vlan_vid(struct packet *pkt, struct ofl_action_vlan_vid *act) {
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->proto->vlan != NULL) {
        struct vlan_header *vlan = pkt->handle_std->proto->vlan;

        vlan->vlan_tci = htons((ntohs(vlan->vlan_tci) & ~VLAN_VID_MASK) |
                               (act->vlan_vid & VLAN_VID_MASK));

        pkt->handle_std->match->dl_vlan = act->vlan_vid;
    } else {
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_VLAN_VID action on packet with no vlan.");
    }
}
Example #6
0
/* Executes set tp src action. */
static void
set_tp_src(struct packet *pkt, struct ofl_action_tp_port *act) {
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->proto->tcp != NULL) {
        struct tcp_header *tcp = pkt->handle_std->proto->tcp;

        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_src, htons(act->tp_port));
        tcp->tcp_src = htons(act->tp_port);

        pkt->handle_std->match->tp_src = act->tp_port;

    } else if (pkt->handle_std->proto->udp != NULL) {
        struct udp_header *udp = pkt->handle_std->proto->udp;

        udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_src, htons(act->tp_port));
        udp->udp_src = htons(act->tp_port);

        pkt->handle_std->match->tp_src = act->tp_port;

    } else {
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_TP_SRC action on packet with no tp.");
    }
}
Example #7
0
/* Executes set tp dst action. */
static void
set_tp_dst(struct packet *pkt, struct ofl_action_tp_port *act) {
    packet_handle_std_validate(pkt->handle_std);
    if (pkt->handle_std->proto->tcp != NULL) {
        struct tcp_header *tcp = pkt->handle_std->proto->tcp;

        tcp->tcp_csum = recalc_csum16(tcp->tcp_csum, tcp->tcp_dst, htons(act->tp_port));
        tcp->tcp_dst = htons(act->tp_port);

        pkt->handle_std->match->tp_dst = act->tp_port;

    } else if (pkt->handle_std->proto->udp != NULL) {
        struct udp_header *udp = pkt->handle_std->proto->udp;

        udp->udp_csum = recalc_csum16(udp->udp_csum, udp->udp_dst, htons(act->tp_port));
        udp->udp_dst = htons(act->tp_port);

        // update packet match (assuming it is of type ofl_match_standard)
        pkt->handle_std->match->tp_dst = act->tp_port;

    } else {
        VLOG_WARN_RL(LOG_MODULE, &rl, "Trying to execute SET_TP_DST action on packet with no tp.");
    }
}
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 #9
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 #10
0
void
meter_entry_apply(struct meter_entry *entry, struct packet **pkt){
	
	size_t b;
	bool drop = false;

    entry->stats->packet_in_count++;
    entry->stats->byte_in_count += (*pkt)->buffer->size;

	b = choose_band(entry, *pkt);
	if(b != -1){
        struct ofl_meter_band_header *band_header = (struct ofl_meter_band_header*)  entry->config->bands[b];
        switch(band_header->type){
            case OFPMBT_DROP:{
                drop = true;
                break;
            }
            case OFPMBT_DSCP_REMARK:{
            	packet_handle_std_validate((*pkt)->handle_std);
    		if ((*pkt)->handle_std->valid)
    		{
                struct ofl_meter_band_dscp_remark *band_header = (struct ofl_meter_band_dscp_remark *)  entry->config->bands[b];
                /* Nothing prevent this band to be used for non-IP packets, so filter them out. Jean II */
                if ((*pkt)->handle_std->proto->ipv4 != NULL) {
                    // Fetch dscp in ipv4 header
                    struct ip_header *ipv4 = (*pkt)->handle_std->proto->ipv4;
                    uint8_t old_drop = ipv4->ip_tos & 0x1C;
                    /* The spec says that we need to increase
                                       the drop precedence of the packet.
                                       We need a valid DSCP out of the process,
                                       so we can only modify dscp if the
                                       drop precedence is low (tos 0x***010**)
                                       or medium (tos 0x***100**). Jean II */
                    if (((old_drop == 0x8) && (band_header->prec_level <= 2)) || ((old_drop == 0x10) && (band_header->prec_level <= 1))) {
                        uint8_t new_drop = old_drop + (band_header->prec_level << 3);
                        uint8_t new_tos = new_drop | (ipv4->ip_tos & 0xE3);
                        uint16_t old_val = htons((ipv4->ip_ihl_ver << 8) + ipv4->ip_tos);
                        uint16_t new_val = htons((ipv4->ip_ihl_ver << 8) + new_tos);
                        ipv4->ip_csum = recalc_csum16(ipv4->ip_csum, old_val, new_val);
                        ipv4->ip_tos = new_tos;
                    }
                }
                else if ((*pkt)->handle_std->proto->ipv6 != NULL){
                    struct ipv6_header *ipv6 = (*pkt)->handle_std->proto->ipv6;
                    uint32_t ipv6_ver_tc_fl = ntohl(ipv6->ipv6_ver_tc_fl);
                    uint32_t old_drop = ipv6_ver_tc_fl & 0x1C00000;
                    if (((old_drop == 0x800000) && (band_header->prec_level <= 2)) || ((old_drop == 0x1000000) && (band_header->prec_level <= 1))){
                        uint32_t prec_level = band_header->prec_level << 23;
                        uint32_t new_drop = old_drop + prec_level;
                        ipv6->ipv6_ver_tc_fl = htonl(new_drop | (ipv6_ver_tc_fl & 0xFE3FFFFF));
                    }
                }
                (*pkt)->handle_std->valid = false;
		}
                break;
            }
            case OFPMBT_EXPERIMENTER:{
                break;
            }
        }
        entry->stats->band_stats[b]->byte_band_count += (*pkt)->buffer->size;
        entry->stats->band_stats[b]->packet_band_count++;
        if (drop){
            VLOG_DBG_RL(LOG_MODULE, &rl, "Dropping packet: rate %d", band_header->rate);
            packet_destroy(*pkt);
            *pkt = NULL;
        }
    }

}
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.");
    }

}