Hi, I was working on a hack which can change the behavior of "mod_vlan_vid" action and behave as "push_vlan" for a quick temporary OF1.1 support. For this, I changed the following two functions: (PS: I am using mininet framework)
FILE: ~/openvswitch/datapath/actions.c FUNCTION: static struct sk_buff *modify_vlan_tci(struct sk_buff *skb, __be16 tci) { struct vlan_ethhdr *vh; __be16 old_tci; if (vlan_tx_tag_present(skb) || skb->protocol != htons(ETH_P_8021Q)) return __vlan_hwaccel_put_tag(skb, ntohs(tci)); skb = make_writable(skb, 0); if (unlikely(!skb)) return NULL; if (unlikely(skb->len < VLAN_ETH_HLEN)) return skb; vh = vlan_eth_hdr(skb); old_tci = vh->h_vlan_TCI; vh->h_vlan_TCI = tci; if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) { __be16 diff[] = { ~old_tci, vh->h_vlan_TCI }; skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum); } return skb; } CHANGED TO: static struct sk_buff *modify_vlan_tci(struct sk_buff *skb, __be16 tci) { struct vlan_ethhdr *vh; __be16 old_tci; if (vlan_tx_tag_present(skb)) { __be16 current_tag; current_tag = vlan_tx_tag_get(skb); skb = __vlan_put_tag(skb,current_tag); return __vlan_hwaccel_put_tag(skb,ntohs(tci)) } else if(skb->protocol != (ETH_P_8021Q)) { return __vlan_hwaccel_put_tag(skb,ntohs(tci)); } skb = make_writable(skb, 0); if (unlikely(!skb)) return NULL; if (unlikely(skb->len < VLAN_ETH_HLEN)) return skb; vh = vlan_eth_hdr(skb); old_tci = vh->h_vlan_TCI; vh->h_vlan_TCI = tci; if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) { __be16 diff[] = { ~old_tci, vh->h_vlan_TCI }; skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum); } return skb; } FILE: ~/openvswitch/lib/dpif-netdev.c FUNCTION: static void dp_netdev_set_dl_tci(struct ofpbuf *packet, uint16_t tci) { struct vlan_eth_header *veh; struct eth_header *eh; eh = packet->l2; if (packet->size >= sizeof(struct vlan_eth_header) && eh->eth_type == htons(ETH_TYPE_VLAN)) { veh = packet->l2; veh->veth_tci = tci; } else { // 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 = (char*)packet->l2 - VLAN_HEADER_LEN; } } CHANGED TO: static void dp_netdev_set_dl_tci(struct ofpbuf *packet, uint16_t tci) { struct vlan_eth_header *veh; struct eth_header *eh; eh = packet->l2; // 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 = (char*)packet->l2 - VLAN_HEADER_LEN; } I have then followed the following steps: make clean ; .//boot.sh ; configure ; make ; sudo make install ; sudo cp ~/openvswitch/datapath/linux-2.6/openvswitch_mod.ko /lib/modules/2.6.38-8-generic/kernel/drivers/net/openvswitch_mod.ko and everything happens smoothly. But on running the mininet, with specifying two "mod_vlan_vid" instructions in the action list, (flow added using 'dpctl') the final packet just seems to have the final VLAN ID, as if my changes din't account to anything. Where am I going wrong ? Does the changes I have made really result in behavior that I intend to see ? Thanking You, Rohit _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev