[ovs-dev] OVS Push VLAN Tag Hack and Problem
Naga Rohit, IIT Guwahati
snagarohit at gmail.com
Wed May 23 05:14:45 UTC 2012
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
More information about the dev
mailing list