From patchwork Wed Feb 17 11:44:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gayathri.manepalli@wipro.com X-Patchwork-Id: 584074 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 9D1D6140291 for ; Wed, 17 Feb 2016 22:45:53 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 3C92C106E7; Wed, 17 Feb 2016 03:45:52 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id B38CB106DC for ; Wed, 17 Feb 2016 03:45:50 -0800 (PST) Received: from bar6.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id E77D01631B7 for ; Wed, 17 Feb 2016 04:45:49 -0700 (MST) X-ASG-Debug-ID: 1455709546-0b3237125792dd0001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar6.cudamail.com with ESMTP id yd4DH0Cg1DdZkqji (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 17 Feb 2016 04:45:47 -0700 (MST) X-Barracuda-Envelope-From: gayathri.manepalli@wipro.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO wipro-chn-out02.wipro.com) (203.91.208.15) by mx1-pf1.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 17 Feb 2016 11:45:43 -0000 Received-SPF: pass (mx1-pf1.cudamail.com: SPF record at wipro.com designates 203.91.208.15 as permitted sender) X-Barracuda-Apparent-Source-IP: 203.91.208.15 X-Barracuda-RBL-IP: 203.91.208.15 X-AuditID: cb5bdd89-f79526d00000152e-66-56c45d640f5f X-Invalid-Recipients: Received: from CHN-OUT-EDG01.wipro.com ( [203.91.201.88]) by wipro-chn-out02.wipro.com (Symantec Mail Security) with SMTP id 32.D1.05422.46D54C65; Wed, 17 Feb 2016 17:15:40 +0530 (IST) Received: from CHN-SNR-MBX-24.wipro.com (10.142.51.125) by CHN-OUT-EDG01.wipro.com (203.91.201.38) with Microsoft SMTP Server (TLS) id 14.3.266.1; Wed, 17 Feb 2016 17:14:46 +0530 Received: from wipro-blr-tls01.wipro.com (203.91.201.116) by CHN-SNR-MBX-24.wipro.com (10.142.51.125) with Microsoft SMTP Server (TLS) id 14.3.266.1; Wed, 17 Feb 2016 17:14:48 +0530 Received: from APC01-HK2-obe.outbound.protection.outlook.com (65.55.88.207) by wipro-blr-tls01.wipro.com (203.91.201.116) with Microsoft SMTP Server (TLS) id 15.0.1104.5; Wed, 17 Feb 2016 17:14:45 +0530 Received: from TY1PR0301MB1056.apcprd03.prod.outlook.com (10.164.96.139) by TY1PR0301MB1053.apcprd03.prod.outlook.com (10.164.96.11) with Microsoft SMTP Server (TLS) id 15.1.409.15; Wed, 17 Feb 2016 11:44:42 +0000 Received: from TY1PR0301MB1056.apcprd03.prod.outlook.com ([10.164.96.139]) by TY1PR0301MB1056.apcprd03.prod.outlook.com ([10.164.96.139]) with mapi id 15.01.0409.017; Wed, 17 Feb 2016 11:44:42 +0000 X-CudaMail-Envelope-Sender: gayathri.manepalli@wipro.com From: To: X-CudaMail-MID: CM-E1-216007805 X-CudaMail-DTE: 021716 X-CudaMail-Originating-IP: 203.91.208.15 Thread-Topic: [ovs-dev][PATCH 1/2] : 802.1ad support in OVS & OVS-DPDK X-ASG-Orig-Subj: [##CM-E1-216007805##][ovs-dev][PATCH 1/2] : 802.1ad support in OVS & OVS-DPDK Thread-Index: AdFpVo4pTX6UrfomSEuM/qIST8nRFwAIe08Q Date: Wed, 17 Feb 2016 11:44:42 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: openvswitch.org; dkim=none (message not signed) header.d=none; openvswitch.org; dmarc=none action=none header.from=wipro.com; x-originating-ip: [203.91.215.216] x-microsoft-exchange-diagnostics: 1; TY1PR0301MB1053; 5:XH5ItSNIHZLxDyeFmOhjWuWmYb7XwuoE1etcpgjJtO+8vJnnD3PJ0AHfMaub/7PdB7eg6kCrBLZ0zXPBruOC7bbFkiPWHa2VsXtqjD7D04SgHwX0J+YhQqGaM7er7ucc7Q2G3NqIZkAnLgxzrWrOag==; 24:bnYdWfENWz4EFWrNQaOY42doa/mNcJuTZPHN7TLmI7exPH/0Knr+XMeHIUsZqOXobYBjDWFAO30GEAirKuSHai+5MveYnRVXIOxEIk3+gKM= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:TY1PR0301MB1053; x-ms-office365-filtering-correlation-id: 4d710f63-a41a-4937-cd61-08d3378fb9db x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(62627912741753); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(61425038)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(61426038)(61427038); SRVR:TY1PR0301MB1053; BCL:0; PCL:0; RULEID:; SRVR:TY1PR0301MB1053; x-forefront-prvs: 085551F5A8 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(53754006)(377424004)(51234002)(54356999)(5001960100002)(3660700001)(10400500002)(5008740100001)(110136002)(87936001)(33656002)(40100003)(50986999)(2351001)(11100500001)(19300405004)(107886002)(122556002)(15975445007)(74316001)(16236675004)(3280700002)(5002640100001)(77096005)(229853001)(2501003)(92566002)(189998001)(19580395003)(2906002)(76576001)(586003)(5004730100002)(19625215002)(1220700001)(2900100001)(1730700002)(66066001)(6116002)(19580405001)(790700001)(5003600100002)(450100001)(3846002)(102836003)(1096002)(86362001)(559001)(579004); DIR:OUT; SFP:1101; SCL:1; SRVR:TY1PR0301MB1053; H:TY1PR0301MB1056.apcprd03.prod.outlook.com; FPR:; SPF:None; MLV:sfv; LANG:en; spamdiagnosticoutput: 1:23 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Feb 2016 11:44:42.6006 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 258ac4e4-146a-411e-9dc8-79a9e12fd6da X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY1PR0301MB1053 X-OrganizationHeadersPreserved: TY1PR0301MB1053.apcprd03.prod.outlook.com X-CrossPremisesHeadersPromoted: CHN-HES-EDG03.wipro.com X-CrossPremisesHeadersFiltered: CHN-HES-EDG03.wipro.com X-CFilter-Loop: Reflected X-GBUdb-Analysis: 0, 203.91.208.15, Ugly c=0.264319 p=-0.230769 Source Normal X-MessageSniffer-Rules: 0-0-0-32767-c X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1455709547 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC5_MJ1963, HTML_MESSAGE, NO_REAL_NAME, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.27100 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 NO_REAL_NAME From: does not include a real name 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 X-Content-Filtered-By: Mailman/MimeDel 2.1.16 Subject: [ovs-dev] [PATCH 1/2] : 802.1ad support in OVS & OVS-DPDK X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@openvswitch.org Sender: "dev" Hi All, Below are the configuration and patch details which provides the 802.1ad support for OVS. Description & configuration : OVS supports the following port types with respect to configuration and datapath handling. 1. Access 2. Trunk 3. Native-tagged. 4. Native-untagged. Access port adds vlan header on ingress and removes vlan header on egress By default trunk passes every VLAN traffic if not configured with any specific VLAN ID's A native-tagged port resembles a trunk port, with the exception that a packet without an 802.1Q header that ingresses on a native-tagged port is in the ''native VLAN'' (specified in the tag column). A native-untagged port resembles a native-tagged port, with the exception that a packet that egresses on a native-untagged port in the native VLAN will not have an 802.1Q header (pop). Apart from above 4, to enable 802.1ad, we have introduced a new mode called "trunk-qinq" Trunk-qinq port operational modes: Trunk-qinq port can be configured to work in two modes shown below 1. Default mode. 2. Qualified C-VLAN mode. Default mode: When you just configure a port as trunk-qinq port as below, it falls into default mode $ovs-vsctl set port eth0 tag=118 vlan_mode=trunk-qinq In Default mode, a trunk-qinq port adds 802.1ad vlan header with vid = <118> for every C-VLAN tagged traffic received on ingress. On egress if the packet to be sent out is already 1ad tagged with vid =<118> then removes the 1ad vlan header and send it out to the trunk port of customer edge bridge. Qualified C-VLAN mode: A trunk-qinq port can be set to work in Qualified C-VLAN mode as follows. $ovs-vsctl set port eth0 tag=118 vlan_mode=trunk-qinq cvlans=10, 20, 30 In Qualified C-VLAN mode, a trunk-qinq port adds 802.1ad vlan header with vid = <118> only for qualified C-VLANS mentioned in cvlans=10, 20, 30. Qualified cvlans are nothing but a set of specific cvlan's receiving from customer; which are to be designated for 802.1ad tunneled. On egress if the packet to be sent out is already 1ad tagged with vid =<118> then removes the 1ad vlan header and send it out to the trunk port of customer edge bridge. Signed-off-by: Manepalli S Gayathri gayathri.manepalli@wipro.com Thanks & Regards, Gayathri The information contained in this electronic message and any attachments to this message are intended for the exclusive use of the addressee(s) and may contain proprietary, confidential or privileged information. If you are not the intended recipient, you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately and destroy all copies of this message and any attachments. WARNING: Computer viruses can be transmitted via email. The recipient should check this email and any attachments for the presence of viruses. The company accepts no liability for any damage caused by any virus transmitted by this email. www.wipro.com --- openvswitch-2.4.0/datapath/actions.c 2015-08-21 05:48:21.014479288 +0530 +++ openvswitch-2.4.0-1ad-3.18/datapath/actions.c 2015-11-03 21:42:29.861054985 +0530 @@ -222,7 +222,6 @@ static int pop_vlan(struct sk_buff *skb, struct sw_flow_key *key) { int err; - err = skb_vlan_pop(skb); if (skb_vlan_tag_present(skb)) invalidate_flow_key(key); @@ -910,6 +909,10 @@ err = push_vlan(skb, key, nla_data(a)); break; + case OVS_ACTION_ATTR_PUSH_1ADVLAN: + err = push_vlan(skb, key, nla_data(a)); + break; + case OVS_ACTION_ATTR_POP_VLAN: err = pop_vlan(skb, key); break; --- openvswitch-2.4.0/datapath/flow_netlink.c 2015-08-21 05:48:21.062479285 +0530 +++ openvswitch-2.4.0-1ad-3.18/datapath/flow_netlink.c 2015-11-03 17:18:54.171216700 +0530 @@ -2037,6 +2037,7 @@ [OVS_ACTION_ATTR_PUSH_MPLS] = sizeof(struct ovs_action_push_mpls), [OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16), [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan), + [OVS_ACTION_ATTR_PUSH_1ADVLAN] = sizeof(struct ovs_action_push_vlan), [OVS_ACTION_ATTR_POP_VLAN] = 0, [OVS_ACTION_ATTR_SET] = (u32)-1, [OVS_ACTION_ATTR_SET_MASKED] = (u32)-1, @@ -2094,6 +2095,15 @@ return -EINVAL; vlan_tci = vlan->vlan_tci; break; + + case OVS_ACTION_ATTR_PUSH_1ADVLAN: + vlan = nla_data(a); + if (vlan->vlan_tpid != htons(ETH_P_8021AD)) + return -EINVAL; + if (!(vlan->vlan_tci & htons(VLAN_TAG_PRESENT))) + return -EINVAL; + vlan_tci = vlan->vlan_tci; + break; case OVS_ACTION_ATTR_RECIRC: break; --- openvswitch-2.4.0/ofproto/ofproto.h 2015-08-21 05:48:21.954479263 +0530 +++ openvswitch-2.4.0-1ad-3.18/ofproto/ofproto.h 2015-11-03 17:18:54.033216701 +0530 @@ -381,7 +381,9 @@ /* Untagged incoming packets are part of 'vlan', as are incoming packets * tagged with 'vlan'. Outgoing packets tagged with 'vlan' are untagged. * Other VLANs in 'trunks' are trunked. */ - PORT_VLAN_NATIVE_UNTAGGED + PORT_VLAN_NATIVE_UNTAGGED, + + PORT_VLAN_TRUNK_QINQ }; /* Configuration of bundles. */ @@ -394,6 +396,7 @@ enum port_vlan_mode vlan_mode; /* Selects mode for vlan and trunks */ int vlan; /* VLAN VID, except for PORT_VLAN_TRUNK. */ unsigned long *trunks; /* vlan_bitmap, except for PORT_VLAN_ACCESS. */ + unsigned long *cvlans; bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */ struct bond_settings *bond; /* Must be nonnull iff if n_slaves > 1. */ --- openvswitch-2.4.0/ofproto/ofproto-dpif-xlate.c 2015-11-03 23:00:31.052007121 +0530 +++ openvswitch-2.4.0-1ad-3.18/ofproto/ofproto-dpif-xlate.c 2015-11-03 23:00:23.771007195 +0530 @@ -117,6 +117,7 @@ int vlan; /* -1=trunk port, else a 12-bit VLAN ID. */ unsigned long *trunks; /* Bitmap of trunked VLANs, if 'vlan' == -1. * NULL if all VLANs are trunked. */ + unsigned long *cvlans; bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */ bool floodable; /* No port has OFPUTIL_PC_NO_FLOOD set? */ }; @@ -443,7 +444,7 @@ static bool input_vid_is_valid(uint16_t vid, struct xbundle *, bool warn); static uint16_t input_vid_to_vlan(const struct xbundle *, uint16_t vid); static void output_normal(struct xlate_ctx *, const struct xbundle *, - uint16_t vlan); + uint16_t vlan, enum port_vlan_mode inport_vlan_mode); /* Optional bond recirculation parameter to compose_output_action(). */ struct xlate_bond_recirc { @@ -453,7 +454,7 @@ }; static void compose_output_action(struct xlate_ctx *, ofp_port_t ofp_port, - const struct xlate_bond_recirc *xr); + const struct xlate_bond_recirc *xr, enum port_vlan_mode vlan_mode); static struct xbridge *xbridge_lookup(struct xlate_cfg *, const struct ofproto_dpif *); @@ -485,7 +486,7 @@ const struct dpif_backer_support *); static void xlate_xbundle_set(struct xbundle *xbundle, enum port_vlan_mode vlan_mode, int vlan, - unsigned long *trunks, bool use_priority_tags, + unsigned long *trunks, unsigned long *cvlans, bool use_priority_tags, const struct bond *bond, const struct lacp *lacp, bool floodable); static void xlate_xport_set(struct xport *xport, odp_port_t odp_port, @@ -601,7 +602,7 @@ static void xlate_xbundle_set(struct xbundle *xbundle, enum port_vlan_mode vlan_mode, int vlan, - unsigned long *trunks, bool use_priority_tags, + unsigned long *trunks, unsigned long *cvlans, bool use_priority_tags, const struct bond *bond, const struct lacp *lacp, bool floodable) { @@ -610,6 +611,7 @@ xbundle->vlan_mode = vlan_mode; xbundle->vlan = vlan; xbundle->trunks = trunks; + xbundle->cvlans = cvlans; xbundle->use_priority_tags = use_priority_tags; xbundle->floodable = floodable; @@ -704,7 +706,7 @@ xlate_xbundle_init(new_xcfg, new_xbundle); xlate_xbundle_set(new_xbundle, xbundle->vlan_mode, - xbundle->vlan, xbundle->trunks, + xbundle->vlan, xbundle->trunks, xbundle->cvlans, xbundle->use_priority_tags, xbundle->bond, xbundle->lacp, xbundle->floodable); LIST_FOR_EACH (xport, bundle_node, &xbundle->xports) { @@ -898,7 +900,7 @@ void xlate_bundle_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle, const char *name, enum port_vlan_mode vlan_mode, int vlan, - unsigned long *trunks, bool use_priority_tags, + unsigned long *trunks, unsigned long *cvlans, bool use_priority_tags, const struct bond *bond, const struct lacp *lacp, bool floodable) { @@ -918,7 +920,7 @@ free(xbundle->name); xbundle->name = xstrdup(name); - xlate_xbundle_set(xbundle, vlan_mode, vlan, trunks, + xlate_xbundle_set(xbundle, vlan_mode, vlan, trunks, cvlans, use_priority_tags, bond, lacp, floodable); } @@ -1433,7 +1435,7 @@ static bool xbundle_trunks_vlan(const struct xbundle *bundle, uint16_t vlan) { - return (bundle->vlan_mode != PORT_VLAN_ACCESS + return ((bundle->vlan_mode != PORT_VLAN_ACCESS && bundle->vlan_mode != PORT_VLAN_TRUNK_QINQ) && (!bundle->trunks || bitmap_is_set(bundle->trunks, vlan))); } @@ -1443,6 +1445,12 @@ return vlan == xbundle->vlan || xbundle_trunks_vlan(xbundle, vlan); } +static bool +xbundle_trunks_cvlan(const struct xbundle *bundle, uint16_t vlan) +{ + return ( !bundle->cvlans || bitmap_is_set(bundle->cvlans, vlan)); +} + static mirror_mask_t xbundle_mirror_out(const struct xbridge *xbridge, struct xbundle *xbundle) { @@ -1584,7 +1592,7 @@ struct xlate_cfg *xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp); struct xbundle *out_xbundle = xbundle_lookup(xcfg, out); if (out_xbundle) { - output_normal(ctx, out_xbundle, vlan); + output_normal(ctx, out_xbundle, vlan, -1); } } else if (vlan != out_vlan && !eth_addr_is_reserved(orig_flow->dl_dst)) { @@ -1593,7 +1601,7 @@ LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) { if (xbundle_includes_vlan(xbundle, out_vlan) && !xbundle_mirror_out(xbridge, xbundle)) { - output_normal(ctx, xbundle, out_vlan); + output_normal(ctx, xbundle, out_vlan, -1); } } } @@ -1614,6 +1622,10 @@ return in_xbundle->vlan; break; + case PORT_VLAN_TRUNK_QINQ: + return in_xbundle->vlan; + break; + case PORT_VLAN_TRUNK: return vid; @@ -1655,6 +1667,23 @@ } return true; + case PORT_VLAN_TRUNK_QINQ: + if (in_xbundle->cvlans) + { + if(!xbundle_trunks_cvlan(in_xbundle, vid)) + { + if (warn) + { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "dropping VLAN %"PRIu16" packet " + "received on port %s not explicitly configured for 1ad trunking " + "VLAN %"PRIu16, vid, in_xbundle->name, vid); + } + return false; + } + } + return true; + case PORT_VLAN_NATIVE_UNTAGGED: case PORT_VLAN_NATIVE_TAGGED: if (!vid) { @@ -1701,6 +1730,9 @@ case PORT_VLAN_NATIVE_UNTAGGED: return vlan == out_xbundle->vlan ? 0 : vlan; + case PORT_VLAN_TRUNK_QINQ: + return 0; + default: OVS_NOT_REACHED(); } @@ -1708,7 +1740,7 @@ static void output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, - uint16_t vlan) + uint16_t vlan, enum port_vlan_mode inport_vlan_mode) { ovs_be16 *flow_tci = &ctx->xin->flow.vlan_tci; uint16_t vid; @@ -1782,7 +1814,11 @@ } *flow_tci = tci; - compose_output_action(ctx, xport->ofp_port, use_recirc ? &xr : NULL); + if (inport_vlan_mode == PORT_VLAN_TRUNK_QINQ) + compose_output_action(ctx, xport->ofp_port, use_recirc ? &xr : NULL, inport_vlan_mode); + else + compose_output_action(ctx, xport->ofp_port, use_recirc ? &xr : NULL,-1); + *flow_tci = old_tci; } @@ -2092,7 +2128,7 @@ mcast_xbundle = xbundle_lookup(xcfg, b->port); if (mcast_xbundle && mcast_xbundle != in_xbundle) { xlate_report(ctx, "forwarding to mcast group port"); - output_normal(ctx, mcast_xbundle, vlan); + output_normal(ctx, mcast_xbundle, vlan, -1); } else if (!mcast_xbundle) { xlate_report(ctx, "mcast group port is unknown, dropping"); } else { @@ -2117,7 +2153,7 @@ mcast_xbundle = xbundle_lookup(xcfg, mrouter->port); if (mcast_xbundle && mcast_xbundle != in_xbundle) { xlate_report(ctx, "forwarding to mcast router port"); - output_normal(ctx, mcast_xbundle, vlan); + output_normal(ctx, mcast_xbundle, vlan, -1); } else if (!mcast_xbundle) { xlate_report(ctx, "mcast router port is unknown, dropping"); } else { @@ -2142,7 +2178,7 @@ mcast_xbundle = xbundle_lookup(xcfg, fport->port); if (mcast_xbundle && mcast_xbundle != in_xbundle) { xlate_report(ctx, "forwarding to mcast flood port"); - output_normal(ctx, mcast_xbundle, vlan); + output_normal(ctx, mcast_xbundle, vlan, -1); } else if (!mcast_xbundle) { xlate_report(ctx, "mcast flood port is unknown, dropping"); } else { @@ -2167,7 +2203,7 @@ mcast_xbundle = xbundle_lookup(xcfg, rport->port); if (mcast_xbundle && mcast_xbundle != in_xbundle) { xlate_report(ctx, "forwarding Report to mcast flagged port"); - output_normal(ctx, mcast_xbundle, vlan); + output_normal(ctx, mcast_xbundle, vlan, -1); } else if (!mcast_xbundle) { xlate_report(ctx, "mcast port is unknown, dropping the Report"); } else { @@ -2181,16 +2217,21 @@ uint16_t vlan) { struct xbundle *xbundle; + ovs_be16 tci = ctx->xin->flow.vlan_tci; + + if (in_xbundle->vlan_mode == PORT_VLAN_TRUNK_QINQ) + ctx->base_flow.vlan_tci = 0; LIST_FOR_EACH (xbundle, list_node, &ctx->xbridge->xbundles) { if (xbundle != in_xbundle && xbundle_includes_vlan(xbundle, vlan) && xbundle->floodable && !xbundle_mirror_out(ctx->xbridge, xbundle)) { - output_normal(ctx, xbundle, vlan); + output_normal(ctx, xbundle, vlan, in_xbundle->vlan_mode); } } ctx->xout->nf_output_iface = NF_OUT_FLOOD; + ctx->xin->flow.vlan_tci = tci; } static void @@ -2349,8 +2390,10 @@ struct xlate_cfg *xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp); struct xbundle *mac_xbundle = xbundle_lookup(xcfg, mac_port); if (mac_xbundle && mac_xbundle != in_xbundle) { + if (in_xbundle->vlan_mode == PORT_VLAN_TRUNK_QINQ) + ctx->base_flow.vlan_tci = 0; xlate_report(ctx, "forwarding to learned port"); - output_normal(ctx, mac_xbundle, vlan); + output_normal(ctx, mac_xbundle, vlan, -1); } else if (!mac_xbundle) { xlate_report(ctx, "learned port is unknown, dropping"); } else { @@ -2734,7 +2777,7 @@ static void compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, - const struct xlate_bond_recirc *xr, bool check_stp) + const struct xlate_bond_recirc *xr, bool check_stp, enum port_vlan_mode vlan_mode) { const struct xport *xport = get_ofp_port(ctx->xbridge, ofp_port); struct flow_wildcards *wc = &ctx->xout->wc; @@ -2955,9 +2998,17 @@ if (out_port != ODPP_NONE) { bool use_masked = ctx->xbridge->support.masked_set_action; - ctx->xout->slow |= commit_odp_actions(flow, &ctx->base_flow, + if( vlan_mode == PORT_VLAN_TRUNK_QINQ) + ctx->xout->slow |= commit_odp_1ad_actions(flow, &ctx->base_flow, ctx->xout->odp_actions, - wc, use_masked); + wc, + use_masked); + else + ctx->xout->slow |= commit_odp_actions(flow, &ctx->base_flow, + ctx->xout->odp_actions, + wc, + use_masked); + if (xr) { struct ovs_action_hash *act_hash; @@ -3017,9 +3068,9 @@ static void compose_output_action(struct xlate_ctx *ctx, ofp_port_t ofp_port, - const struct xlate_bond_recirc *xr) + const struct xlate_bond_recirc *xr, enum port_vlan_mode vlan_mode) { - compose_output_action__(ctx, ofp_port, xr, true); + compose_output_action__(ctx, ofp_port, xr, true, vlan_mode); } static void @@ -3412,9 +3463,9 @@ } if (all) { - compose_output_action__(ctx, xport->ofp_port, NULL, false); + compose_output_action__(ctx, xport->ofp_port, NULL, false, -1); } else if (!(xport->config & OFPUTIL_PC_NO_FLOOD)) { - compose_output_action(ctx, xport->ofp_port, NULL); + compose_output_action(ctx, xport->ofp_port, NULL, -1); } } @@ -3668,7 +3719,7 @@ switch (port) { case OFPP_IN_PORT: - compose_output_action(ctx, ctx->xin->flow.in_port.ofp_port, NULL); + compose_output_action(ctx, ctx->xin->flow.in_port.ofp_port, NULL, -1); break; case OFPP_TABLE: xlate_table_action(ctx, ctx->xin->flow.in_port.ofp_port, @@ -3695,7 +3746,7 @@ case OFPP_LOCAL: default: if (port != ctx->xin->flow.in_port.ofp_port) { - compose_output_action(ctx, port, NULL); + compose_output_action(ctx, port, NULL, -1); } else { xlate_report(ctx, "skipping output to input port"); } @@ -3754,7 +3805,7 @@ /* Add datapath actions. */ flow_priority = ctx->xin->flow.skb_priority; ctx->xin->flow.skb_priority = priority; - compose_output_action(ctx, ofp_port, NULL); + compose_output_action(ctx, ofp_port, NULL, -1); ctx->xin->flow.skb_priority = flow_priority; /* Update NetFlow output port. */ @@ -4261,7 +4312,7 @@ sizeof wc->masks.skb_priority); xlate_set_queue_action(ctx, ofpact_get_SET_QUEUE(a)->queue_id); break; - + case OFPACT_POP_QUEUE: memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority); @@ -4977,7 +5028,7 @@ && xbridge->has_in_band && in_band_must_output_to_local_port(flow) && !actions_output_to_local_port(&ctx)) { - compose_output_action(&ctx, OFPP_LOCAL, NULL); + compose_output_action(&ctx, OFPP_LOCAL, NULL, -1); } if (!xin->recirc) { --- openvswitch-2.4.0/ofproto/ofproto-dpif.c 2015-08-21 05:48:21.902479262 +0530 +++ openvswitch-2.4.0-1ad-3.18/ofproto/ofproto-dpif.c 2015-11-03 17:18:54.033216701 +0530 @@ -137,6 +137,7 @@ int vlan; /* -1=trunk port, else a 12-bit VLAN ID. */ unsigned long *trunks; /* Bitmap of trunked VLANs, if 'vlan' == -1. * NULL if all VLANs are trunked. */ + unsigned long *cvlans; struct lacp *lacp; /* LACP if LACP is enabled, otherwise NULL. */ struct bond *bond; /* Nonnull iff more than one port. */ bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */ @@ -646,7 +647,7 @@ HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) { xlate_bundle_set(ofproto, bundle, bundle->name, bundle->vlan_mode, bundle->vlan, - bundle->trunks, bundle->use_priority_tags, + bundle->trunks, bundle->cvlans, bundle->use_priority_tags, bundle->bond, bundle->lacp, bundle->floodable); } @@ -2768,6 +2769,7 @@ struct ofport_dpif *port; struct ofbundle *bundle; unsigned long *trunks; + unsigned long *cvlans; int vlan; size_t i; bool ok; @@ -2794,6 +2796,7 @@ bundle->vlan_mode = PORT_VLAN_TRUNK; bundle->vlan = -1; bundle->trunks = NULL; + bundle->cvlans = NULL; bundle->use_priority_tags = s->use_priority_tags; bundle->lacp = NULL; bundle->bond = NULL; @@ -2870,14 +2873,22 @@ switch (s->vlan_mode) { case PORT_VLAN_ACCESS: trunks = NULL; + cvlans = NULL; break; case PORT_VLAN_TRUNK: trunks = CONST_CAST(unsigned long *, s->trunks); + cvlans = NULL; + break; + + case PORT_VLAN_TRUNK_QINQ: + trunks = NULL; + cvlans = CONST_CAST(unsigned long *, s->cvlans); break; case PORT_VLAN_NATIVE_UNTAGGED: case PORT_VLAN_NATIVE_TAGGED: + cvlans = NULL; if (vlan != 0 && (!s->trunks || !bitmap_is_set(s->trunks, vlan) || bitmap_is_set(s->trunks, 0))) { @@ -2910,6 +2921,25 @@ if (trunks != s->trunks) { free(trunks); } + + if (!vlan_bitmap_equal(cvlans, bundle->cvlans)) + { + free(bundle->cvlans); + if (cvlans == s->cvlans) + { + bundle->cvlans = vlan_bitmap_clone(cvlans); + } + else + { + bundle->cvlans = cvlans; + cvlans = NULL; + } + need_flush = true; + } + if (cvlans != s->cvlans) + { + free(cvlans); + } /* Bonding. */ if (!list_is_short(&bundle->ports)) { --- openvswitch-2.4.0/vswitchd/bridge.c 2015-08-21 05:48:22.362479252 +0530 +++ openvswitch-2.4.0-1ad-3.18/vswitchd/bridge.c 2015-11-03 17:18:53.900216703 +0530 @@ -934,6 +934,8 @@ if (cfg->vlan_mode) { if (!strcmp(cfg->vlan_mode, "access")) { s.vlan_mode = PORT_VLAN_ACCESS; + } else if (!strcmp(cfg->vlan_mode, "trunk-qinq")) { + s.vlan_mode = PORT_VLAN_TRUNK_QINQ; } else if (!strcmp(cfg->vlan_mode, "trunk")) { s.vlan_mode = PORT_VLAN_TRUNK; } else if (!strcmp(cfg->vlan_mode, "native-tagged")) { @@ -959,6 +961,11 @@ } s.use_priority_tags = smap_get_bool(&cfg->other_config, "priority-tags", false); + s.cvlans = NULL; + if (cfg->n_cvlans) + { + s.cvlans = vlan_bitmap_from_array(cfg->cvlans, cfg->n_cvlans); + } /* Get LACP settings. */ s.lacp = port_configure_lacp(port, &lacp_settings); --- openvswitch-2.4.0/vswitchd/vswitch.ovsschema 2015-08-12 02:08:18.123317347 +0530 +++ openvswitch-2.4.0-1ad-3.18/vswitchd/vswitch.ovsschema 2015-11-03 17:18:53.900216703 +0530 @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", "version": "7.12.1", - "cksum": "2211824403 22535", + "cksum": "3377693257 22744", "tables": { "Open_vSwitch": { "columns": { @@ -144,6 +144,11 @@ "minInteger": 0, "maxInteger": 4095}, "min": 0, "max": 4096}}, + "cvlans": { + "type": {"key": {"type": "integer", + "minInteger": 0, + "maxInteger": 4095}, + "min": 0, "max": 4096}}, "tag": { "type": {"key": {"type": "integer", "minInteger": 0, @@ -151,7 +156,7 @@ "min": 0, "max": 1}}, "vlan_mode": { "type": {"key": {"type": "string", - "enum": ["set", ["trunk", "access", "native-tagged", "native-untagged"]]}, + "enum": ["set", ["trunk","trunk-qinq","access", "native-tagged", "native-untagged"]]}, "min": 0, "max": 1}}, "qos": { "type": {"key": {"type": "uuid", --- openvswitch-2.4.0/datapath/linux/compat/include/linux/openvswitch.h 2015-08-21 05:48:21.074479285 +0530 +++ openvswitch-2.4.0-1ad-3.18/datapath/linux/compat/include/linux/openvswitch.h 2015-11-03 17:18:54.175216700 +0530 @@ -690,6 +690,7 @@ OVS_ACTION_ATTR_USERSPACE, /* Nested OVS_USERSPACE_ATTR_*. */ OVS_ACTION_ATTR_SET, /* One nested OVS_KEY_ATTR_*. */ OVS_ACTION_ATTR_PUSH_VLAN, /* struct ovs_action_push_vlan. */ + OVS_ACTION_ATTR_PUSH_1ADVLAN, OVS_ACTION_ATTR_POP_VLAN, /* No argument. */ OVS_ACTION_ATTR_SAMPLE, /* Nested OVS_SAMPLE_ATTR_*. */ OVS_ACTION_ATTR_RECIRC, /* u32 recirc_id. */ --- openvswitch-2.4.0/lib/odp-util.c 2015-08-21 05:48:28.218479104 +0530 +++ openvswitch-2.4.0-1ad-3.18/lib/odp-util.c 2015-11-03 17:18:53.924216702 +0530 @@ -93,6 +93,7 @@ case OVS_ACTION_ATTR_TUNNEL_POP: return sizeof(uint32_t); case OVS_ACTION_ATTR_USERSPACE: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_PUSH_VLAN: return sizeof(struct ovs_action_push_vlan); + case OVS_ACTION_ATTR_PUSH_1ADVLAN: return sizeof(struct ovs_action_push_vlan); case OVS_ACTION_ATTR_POP_VLAN: return 0; case OVS_ACTION_ATTR_PUSH_MPLS: return sizeof(struct ovs_action_push_mpls); case OVS_ACTION_ATTR_POP_MPLS: return sizeof(ovs_be16); @@ -695,6 +696,8 @@ format_vlan_tci(ds, vlan->vlan_tci, OVS_BE16_MAX, false); ds_put_char(ds, ')'); break; + case OVS_ACTION_ATTR_PUSH_1ADVLAN: //to be handled via openflow + break; case OVS_ACTION_ATTR_POP_VLAN: ds_put_cstr(ds, "pop_vlan"); break; @@ -4543,6 +4546,29 @@ base->vlan_tci = vlan_tci; } +static void +commit_vlan_1ad_action(ovs_be16 vlan_tci, struct flow *base, + struct ofpbuf *odp_actions, struct flow_wildcards *wc) +{ + if (base->vlan_tci == vlan_tci) { + return; + } + + pop_vlan(base, odp_actions, wc); + + if (vlan_tci & htons(VLAN_CFI)) + { + struct ovs_action_push_vlan vlan; + + vlan.vlan_tpid = htons(ETH_TYPE_VLAN_8021AD); + vlan.vlan_tci = vlan_tci; + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_1ADVLAN, + &vlan, sizeof vlan); + } + + base->vlan_tci = vlan_tci; +} + /* Wildcarding already done at action translation time. */ static void commit_mpls_action(const struct flow *flow, struct flow *base, @@ -4935,3 +4961,20 @@ return slow; } + +enum slow_path_reason +commit_odp_1ad_actions(const struct flow *flow, struct flow *base, + struct ofpbuf *odp_actions, struct flow_wildcards *wc, + bool use_masked) +{ + enum slow_path_reason slow; + commit_set_ether_addr_action(flow, base, odp_actions, wc, use_masked); + slow = commit_set_nw_action(flow, base, odp_actions, wc, use_masked); + commit_set_port_action(flow, base, odp_actions, wc, use_masked); + commit_mpls_action(flow, base, odp_actions); + commit_vlan_1ad_action(flow->vlan_tci, base, odp_actions, wc); + commit_set_priority_action(flow, base, odp_actions, wc, use_masked); + commit_set_pkt_mark_action(flow, base, odp_actions, wc, use_masked); + return slow; +} + --- openvswitch-2.4.0/lib/odp-util.h 2015-08-21 05:48:21.486479273 +0530 +++ openvswitch-2.4.0-1ad-3.18/lib/odp-util.h 2015-11-03 17:18:53.930216702 +0530 @@ -203,6 +203,13 @@ struct ofpbuf *odp_actions, struct flow_wildcards *wc, bool use_masked); +enum slow_path_reason commit_odp_1ad_actions(const struct flow *, + struct flow *base, + struct ofpbuf *odp_actions, + struct flow_wildcards *wc, + bool use_masked); + + /* ofproto-dpif interface. * --- openvswitch-2.4.0/ofproto/ofproto-dpif-xlate.h 2015-08-21 05:48:21.874479265 +0530 +++ openvswitch-2.4.0-1ad-3.18/ofproto/ofproto-dpif-xlate.h 2015-11-03 17:18:54.031216701 +0530 @@ -216,7 +216,7 @@ void xlate_bundle_set(struct ofproto_dpif *, struct ofbundle *, const char *name, enum port_vlan_mode, int vlan, - unsigned long *trunks, bool use_priority_tags, + unsigned long *trunks, unsigned long *cvlans, bool use_priority_tags, const struct bond *, const struct lacp *, bool floodable); void xlate_bundle_remove(struct ofbundle *); --- openvswitch-2.4.0/vswitchd/vswitch.xml 2015-08-21 05:48:22.394479252 +0530 +++ openvswitch-2.4.0-1ad-3.18/vswitchd/vswitch.xml 2015-11-03 17:18:53.902216703 +0530 @@ -1170,6 +1170,13 @@ exception that a packet that egresses on a native-untagged port in the native VLAN will not have an 802.1Q header. +
trunk-qinq
+
+ A trunk-qinq port adds 802.1ad header to untagged packet received and adds + outer vlan header(1ad) to already tagged packet on ingress.On egress pops the + outer vlan header if the outer vlan vid matches the configured outer vid +
+

A packet will only egress through bridge ports that carry the VLAN of @@ -1213,6 +1220,13 @@ VLAN.

+ +

+ For a trunk-qinq port if specific cvlans are specified only those + cvlans are 1ad tunneled, others are dropped. If no cvlans specified + explicitly then all cvlans are 1ad tunneled. +

+
--- openvswitch-2.4.0/lib/odp-execute.c 2015-08-21 05:48:21.442479276 +0530 +++ openvswitch-2.4.0-1ad-3.18/lib/odp-execute.c 2015-11-03 17:18:53.954216702 +0530 @@ -481,6 +481,7 @@ case OVS_ACTION_ATTR_SET: case OVS_ACTION_ATTR_SET_MASKED: case OVS_ACTION_ATTR_PUSH_VLAN: + case OVS_ACTION_ATTR_PUSH_1ADVLAN: case OVS_ACTION_ATTR_POP_VLAN: case OVS_ACTION_ATTR_SAMPLE: case OVS_ACTION_ATTR_HASH: @@ -560,6 +561,9 @@ break; } + case OVS_ACTION_ATTR_PUSH_1ADVLAN: //to be handled via openflow mode + break; + case OVS_ACTION_ATTR_POP_VLAN: for (i = 0; i < cnt; i++) { eth_pop_vlan(packets[i]); --- openvswitch-2.4.0/lib/dpif.c 2015-08-21 05:48:21.262479281 +0530 +++ openvswitch-2.4.0-1ad-3.18/lib/dpif.c 2015-11-03 17:18:53.949216702 +0530 @@ -1135,6 +1135,7 @@ case OVS_ACTION_ATTR_HASH: case OVS_ACTION_ATTR_PUSH_VLAN: + case OVS_ACTION_ATTR_PUSH_1ADVLAN: case OVS_ACTION_ATTR_POP_VLAN: case OVS_ACTION_ATTR_PUSH_MPLS: case OVS_ACTION_ATTR_POP_MPLS: --- openvswitch-2.4.0/lib/dpif-netdev.c 2015-08-21 05:48:21.218479282 +0530 +++ openvswitch-2.4.0-1ad-3.18/lib/dpif-netdev.c 2015-11-03 17:18:53.944216702 +0530 @@ -3529,6 +3529,7 @@ break; case OVS_ACTION_ATTR_PUSH_VLAN: + case OVS_ACTION_ATTR_PUSH_1ADVLAN: case OVS_ACTION_ATTR_POP_VLAN: case OVS_ACTION_ATTR_PUSH_MPLS: case OVS_ACTION_ATTR_POP_MPLS: --- openvswitch-2.4.0/lib/flow.c 2015-08-21 05:48:21.306479280 +0530 +++ openvswitch-2.4.0-1ad-3.18/lib/flow.c 2015-11-03 17:18:53.932216702 +0530 @@ -298,6 +298,14 @@ return qp->tci | htons(VLAN_CFI); } } + if (eth->eth_type == htons(ETH_TYPE_VLAN_8021AD)) { + if (OVS_LIKELY(*sizep + >= sizeof(struct qtag_prefix) + sizeof(ovs_be16))) { + const struct qtag_prefix *qp = data_pull(datap, sizep, sizeof *qp); + return qp->tci | htons(VLAN_CFI); + } + } + return 0; } --- openvswitch-2.4.0/.travis.yml 2015-08-21 05:48:20.842479290 +0530 +++ openvswitch-2.4.0-1ad-3.18/.travis.yml 2015-11-03 17:18:54.227216699 +0530 @@ -13,7 +13,7 @@ - KERNEL=4.0.2 - KERNEL=3.17.7 DPDK=1 - KERNEL=3.17.7 DPDK=1 OPTS="--enable-shared" - - KERNEL=3.17.7 + - KERNEL=3.18.22 - KERNEL=3.16.7 - KERNEL=3.14.27 - KERNEL=3.12.35 --- openvswitch-2.4.0/acinclude.m4 2015-08-20 22:21:36.258995254 +0530 +++ openvswitch-2.4.0-1ad-3.18/acinclude.m4 2015-11-03 17:18:54.227216699 +0530 @@ -322,6 +322,7 @@ OVS_GREP_IFELSE([$KSRC/include/linux/etherdevice.h], [ether_addr_copy]) OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [vlan_set_encap_proto]) + OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [vlan_hwaccel_push_inside]) OVS_GREP_IFELSE([$KSRC/include/linux/in.h], [ipv4_is_multicast]) OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [__ip_select_ident.*dst_entry], --- openvswitch-2.4.0/datapath/linux/compat/include/linux/if_vlan.h 2015-08-12 02:08:17.439292814 +0530 +++ openvswitch-2.4.0-1ad-3.18/datapath/linux/compat/include/linux/if_vlan.h 2015-11-03 17:18:54.176216700 +0530 @@ -52,7 +52,7 @@ } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +#ifndef HAVE_VLAN_HWACCEL_PUSH_INSIDE /* * __vlan_hwaccel_push_inside - pushes vlan tag to the payload * @skb: skbuff to tag