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