/* Copies the 'size' bytes starting at 'p' to the head end of 'b', reallocating * and copying its data if necessary. Returns a pointer to the first byte of * the data's location in the ofpbuf. */ void * ofpbuf_push(struct ofpbuf *b, const void *p, size_t size) { void *dst = ofpbuf_push_uninit(b, size); memcpy(dst, p, size); return dst; }
/* Prefixes 'size' zeroed bytes to the head end of 'b', reallocating and * copying its data if necessary. Returns a pointer to the first byte of the * data's location in the ofpbuf. */ void * ofpbuf_push_zeros(struct ofpbuf *b, size_t size) { void *dst = ofpbuf_push_uninit(b, size); memset(dst, 0, size); return dst; }
/* v6inv4 push action only makes the value be zero! set action is responsible for setting. */ void push_v4(struct ofpbuf *packet, ovs_be16 ethtype) { struct v4_eth_header *veh; struct eth_header *eh; struct ipv6_header *ih; eh = packet->l2; ih = packet->l3; if(packet->size >= sizeof(struct eth_header) && eh->eth_type == htons(ETH_TYPE_IPV6)){ /* push and copy from ipv6 header */ struct v4_eth_header tmp; memcpy(tmp.eth_dst, eh->eth_dst, ETH_ADDR_LEN); memcpy(tmp.eth_src, eh->eth_src, ETH_ADDR_LEN); tmp.eth_type = ethtype; set_v4_values(&tmp.ip_ihl_ver, &tmp.ip_tot_len, &tmp.ip_ttl, ih->ipv6_loadlen, ih->ipv6_ttl, 0, 0); veh = ofpbuf_push_uninit(packet, V4_HLEN); memcpy(veh, &tmp, sizeof tmp); packet->l2 = (char*)packet->l2 - V4_HLEN; packet->l2_5 = (char*)packet->l2 + sizeof(struct eth_header); } else { /* not ipv6? then, we do not do anything now. */ } /* push on the new label */ }
/* v4inv6 push action only makes the value be zero! set action is responsible for seting. */ void push_v6(struct ofpbuf *packet, ovs_be16 ethtype) { struct v6_eth_header *veh; struct eth_header *eh; struct ip_header *ih; eh = packet->l2; ih = packet->l3; printf("packets.c:push_v6: ethtype=0x%x\n", ethtype); printf("packets.c:push_v6: eh->eth_type=0x%x\n", eh->eth_type); if(packet->size >= sizeof(struct eth_header) && eh->eth_type == htons(ETH_TYPE_IP)) { /* push and copy from ip header */ struct v6_eth_header tmp; memcpy(tmp.eth_dst, eh->eth_dst, ETH_ADDR_LEN); memcpy(tmp.eth_src, eh->eth_src, ETH_ADDR_LEN); tmp.eth_type = ethtype; set_v6_values(&tmp.v6_version_class_label,&tmp.v6_loadlength_nexthead_ttl,ih->ip_tot_len,ih->ip_ttl,0,0); veh = ofpbuf_push_uninit(packet, V6_HLEN); memcpy(veh, &tmp, sizeof tmp); packet->l2 = (char*)packet->l2 - V6_HLEN; packet->l2_5 = (char*)packet->l2 + sizeof (struct eth_header); } else { /* not ipv4? then ,we do not do anything now.*/ } /* push on the new label */ }
/* Insert VLAN header according to given TCI. Packet passed must be Ethernet * packet. * * Also sets 'packet->l2' to point to the new Ethernet header. */ void eth_push_vlan(struct ofpbuf *packet, ovs_be16 tci) { struct eth_header *eh = packet->data; struct vlan_eth_header *veh; /* Insert new 802.1Q header. */ struct vlan_eth_header tmp; memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN); memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN); tmp.veth_type = htons(ETH_TYPE_VLAN); tmp.veth_tci = tci; tmp.veth_next_type = eh->eth_type; veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN); memcpy(veh, &tmp, sizeof tmp); packet->l2 = packet->data; }