OVSDB project's OpenFlow 1.3 ProtocolPlugin integration via Controller's MD-SAL infra... 89/3889/1
authorMadhu Venugopal <mavenugo@gmail.com>
Sat, 21 Dec 2013 21:57:39 +0000 (13:57 -0800)
committerMadhu Venugopal <mavenugo@gmail.com>
Sat, 21 Dec 2013 21:57:39 +0000 (13:57 -0800)
This checkin brings in the basic infrastructure changes needed to integrate the ovsdb.neutron bundle
with OpenFlow1.3 via the Controller's MDSAL infrastructure. The actual work of mapping the multi-table
and various Flow programming can be done now over this infra.

Change-Id: Ia3b73e4be243fe597c8996a676cd648c6a960d62
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
neutron/pom.xml
neutron/src/main/java/org/opendaylight/ovsdb/neutron/Activator.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/IMDSALConsumer.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/InternalNetworkManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/MDSALConsumer.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10ProviderManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF13ProviderManager.java
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/table/Bridge.java

index b96dad54f2b0739d7d9f2923a6b6c260fa0e6aab..b6ff856e67a9a8a696c63778d37a4e176158fe13 100644 (file)
       <tag>HEAD</tag>
     </scm>
 
+    <properties>
+        <guava.version>14.0.1</guava.version>
+        <xtend.version>2.4.3</xtend.version>
+        <bundle.plugin.version>2.4.0</bundle.plugin.version>
+        <maven.clean.plugin.version>2.5</maven.clean.plugin.version>
+    </properties>
   <build>
     <plugins>
       <plugin>
               org.opendaylight.ovsdb.lib.notation,
               org.opendaylight.ovsdb.lib.table,
               org.opendaylight.ovsdb.lib.table.internal,
+              org.opendaylight.controller.sal.binding.api,
+              org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
+              org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes,
+              org.opendaylight.yangtools.yang.binding,
               org.apache.felix.dm,
               org.slf4j,
-              org.osgi.framework
+              org.osgi.framework,
+              *
             </Import-Package>
             <Bundle-Activator>
               org.opendaylight.ovsdb.neutron.Activator
       <artifactId>containermanager</artifactId>
       <version>0.5.1-SNAPSHOT</version>
     </dependency>
+    <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-binding-api</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+        <groupId>org.opendaylight.controller.model</groupId>
+        <artifactId>model-flow-service</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-flow-base</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+   <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-flow-management</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-inventory</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-binding</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-util</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index 984a335b9e23cb06c57078ab1f036deca8c002ea..c123714d0ab56e98dfe8bf2c73166ff95c14cb8b 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;
 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
 import org.opendaylight.controller.switchmanager.IInventoryListener;
 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
@@ -58,7 +59,8 @@ public class Activator extends ComponentActivatorAbstractBase {
         Object[] res = {NetworkHandler.class,
                         SubnetHandler.class,
                         PortHandler.class,
-                        SouthboundHandler.class};
+                        SouthboundHandler.class,
+                        MDSALConsumer.class};
         return res;
     }
 
@@ -94,6 +96,14 @@ public class Activator extends ComponentActivatorAbstractBase {
             c.setInterface(new String[] {OVSDBInventoryListener.class.getName(), IInventoryListener.class.getName()}, null);
         }
 
+        if (imp.equals(MDSALConsumer.class)) {
+            c.setInterface(IMDSALConsumer.class.getName(), null);
+
+            c.add(createServiceDependency()
+                    .setService(BindingAwareBroker.class)
+                    .setCallbacks("setBindingAwareBroker", "unsetBindingAwareBroker")
+                    .setRequired(true));
+        }
         c.add(createServiceDependency().
                 setService(OVSDBConfigService.class).
                 setCallbacks("setOVSDBConfigService", "unsetOVSDBConfigService").
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/IMDSALConsumer.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/IMDSALConsumer.java
new file mode 100644 (file)
index 0000000..d4c2c90
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Authors : Madhu Venugopal
+ */
+
+package org.opendaylight.ovsdb.neutron;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+
+public interface IMDSALConsumer {
+    public ConsumerContext getConsumerContext();
+    public DataBrokerService getDataBrokerService();
+}
index aced03c4b3563cfd11eb96157131b9f9297a6f93..b11ada9353fb2b8fafa3c249b9bce947d2a6edab 100644 (file)
@@ -112,8 +112,10 @@ public class InternalNetworkManager {
 
         Status status = this.addInternalBridge(node, brInt, patchTun, patchInt);
         if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
-        status = this.addInternalBridge(node, brTun, patchInt, patchTun);
-        if (!status.isSuccess()) logger.debug("Tunnel Bridge Creation Status : "+status.toString());
+        if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
+            status = this.addInternalBridge(node, brTun, patchInt, patchTun);
+            if (!status.isSuccess()) logger.debug("Tunnel Bridge Creation Status : "+status.toString());
+        }
     }
 
     /*
@@ -138,6 +140,11 @@ public class InternalNetworkManager {
         if (bridgeUUID == null) {
             Bridge bridge = new Bridge();
             bridge.setName(bridgeName);
+            if (!ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
+                OvsDBSet<String> protocols = new OvsDBSet<String>();
+                protocols.add("OpenFlow13");
+                bridge.setProtocols(protocols);
+            }
 
             StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, bridge);
             if (!statusWithUuid.isSuccess()) return statusWithUuid;
@@ -150,7 +157,7 @@ public class InternalNetworkManager {
         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
         connectionService.setOFController(node, bridgeUUID);
 
-        if (localPathName != null && remotePatchName != null) {
+        if (localPathName != null && remotePatchName != null && ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
             return addPatchPort(node, bridgeUUID, localPathName, remotePatchName);
         }
         return new Status(StatusCode.SUCCESS);
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/MDSALConsumer.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/MDSALConsumer.java
new file mode 100644 (file)
index 0000000..a103106
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Authors : Madhu Venugopal
+ */
+
+package org.opendaylight.ovsdb.neutron;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+public class MDSALConsumer implements BindingAwareConsumer, IMDSALConsumer {
+
+    private BundleContext ctx = null;
+    private BindingAwareBroker broker = null;
+    private ConsumerContext consumerContext = null;
+    private DataBrokerService dataBrokerService;
+
+    static final Logger logger = LoggerFactory.getLogger(MDSALConsumer.class);
+
+    void setBindingAwareBroker (BindingAwareBroker b) {
+        this.broker = b;
+    }
+
+    void unsetBindingAwareBroker(BindingAwareBroker b) {
+        if (this.broker == b) {
+            this.broker = null;
+        }
+    }
+
+    void init(Component c) {
+        this.ctx = c.getDependencyManager().getBundleContext();
+        logger.info("****** OVSDB Neutron Registered with MD-SAL ******");
+        broker.registerConsumer(this, this.ctx);
+    }
+
+    void destroy() {
+        // Now lets close MDSAL session
+        if (this.consumerContext != null) {
+            //this.consumerContext.close();
+            this.consumerContext = null;
+        }
+    }
+
+    void start() {
+    }
+
+    void stop() {
+    }
+
+    @Override
+    public void onSessionInitialized(ConsumerContext session) {
+        this.consumerContext = session;
+        dataBrokerService = session.getSALService(DataBrokerService.class);
+        logger.info("****** OVSDB Neutron Session Initilized with CONSUMER CONTEXT {} ******", session.toString());
+    }
+
+    @Override
+    public ConsumerContext getConsumerContext() {
+        return consumerContext;
+    }
+    @Override
+    public DataBrokerService getDataBrokerService() {
+        return dataBrokerService;
+    }
+}
index 1e8f708bf14828dc33e4739454334e6c8d9553a1..dc2d339a331fdd4dc70e7a017558d9f904f7fb03 100644 (file)
@@ -461,6 +461,7 @@ class OF10ProviderManager extends ProviderNetworkManager {
             for (Switch device : nodes) {
                 if (device.getNode().equals(ofNode)) {
                     logger.debug("Initialize OF Flows on {}", ofNode);
+                    initializeNormalFlowRules(ofNode);
                     return;
                 }
             }
index d1e98732ca541e3cc72d86183bbcfaa79f26b7f2..f42c6a5dc1605e92a7f30dc8017bb111996c7d8d 100644 (file)
@@ -9,12 +9,63 @@
  */
 package org.opendaylight.ovsdb.neutron.provider;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.HexEncode;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.ovsdb.lib.table.Bridge;
 import org.opendaylight.ovsdb.lib.table.Interface;
+import org.opendaylight.ovsdb.neutron.AdminConfigManager;
+import org.opendaylight.ovsdb.neutron.IMDSALConsumer;
+import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
 
 class OF13ProviderManager extends ProviderNetworkManager {
+    private static final Logger logger = LoggerFactory.getLogger(OF13ProviderManager.class);
+    private DataBrokerService dataBrokerService;
+
     @Override
     public boolean hasPerTenantTunneling() {
         return false;
@@ -34,9 +85,136 @@ class OF13ProviderManager extends ProviderNetworkManager {
 
     @Override
     public void initializeFlowRules(Node node) {
+        this.initializeFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName());
+    }
+
+    private void initializeFlowRules(Node node, String bridgeName) {
+        try {
+            // TODO : 3 second sleep hack is to make sure the OF connection is established.
+            // Correct fix is to check the MD-SAL inventory before proceeding and listen
+            // to Inventory update for processing.
+            Thread.sleep(3000);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        String brIntId = this.getInternalBridgeUUID(node, bridgeName);
+        if (brIntId == null) {
+            logger.error("Failed to initialize Flow Rules for {}", node);
+            return;
+        }
+
+        try {
+            OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+            Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+            Set<String> dpids = bridge.getDatapath_id();
+            if (dpids == null || dpids.size() ==  0) return;
+            Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
+            writeLLDPRule(dpidLong);
+        } catch (Exception e) {
+            logger.error("Failed to initialize Flow Rules for "+node.toString(), e);
+        }
+    }
+
+    private void writeLLDPRule(Long dpidLong) {
+        String nodeName = "openflow:"+dpidLong;
+        NodeBuilder tn = createNodeBuilder(nodeName);
+        FlowBuilder flow = new FlowBuilder();
+        flow.setMatch(createLLDPMatch().build());
+        flow.setInstructions(this.createSentToControllerInstructions().build());
+        // TODO : Investigate the need for this.
+        FlowKey key = new FlowKey(new FlowId(new Long(123)));
+        flow.setBarrier(false);
+        flow.setTableId((short)0);
+        flow.setKey(key);
+        flow.setFlowName("LLDP_" + nodeName);
+        writeFlow(flow, tn);
+    }
+
+    private void writeFlow(FlowBuilder flow, NodeBuilder nodeBuilder) {
+        IMDSALConsumer mdsalConsumer = (IMDSALConsumer)ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+        if (mdsalConsumer == null) {
+            logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+            return;
+        }
+
+        dataBrokerService = mdsalConsumer.getDataBrokerService();
+
+        if (dataBrokerService == null) {
+            logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+            return;
+        }
+        DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
+        InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flow.getKey())
+                .build();
+        modification.putOperationalData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
+        modification.putOperationalData(path1, flow.build());
+        modification.putConfigurationData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
+        modification.putConfigurationData(path1, flow.build());
+        Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
+        try {
+            RpcResult<TransactionStatus> result = commitFuture.get();
+            TransactionStatus status = result.getResult();
+        } catch (InterruptedException e) {
+            logger.error(e.getMessage(), e);
+        } catch (ExecutionException e) {
+            logger.error(e.getMessage(), e);
+        }
+    }
+
+    private static MatchBuilder createLLDPMatch() {
+        MatchBuilder match = new MatchBuilder();
+        EthernetMatchBuilder eth = new EthernetMatchBuilder();
+        EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+        ethTypeBuilder.setType(new EtherType(0x88CCL));
+        eth.setEthernetType(ethTypeBuilder.build());
+        match.setEthernetMatch(eth.build());
+        return match;
+    }
+
+    private InstructionsBuilder createSentToControllerInstructions() {
+        List<Action> actionList = new ArrayList<Action>();
+        ActionBuilder ab = new ActionBuilder();
+
+        OutputActionBuilder output = new OutputActionBuilder();
+        output.setMaxLength(56);
+        Uri value = new Uri("CONTROLLER");
+        output.setOutputNodeConnector(value);
+        ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
+        actionList.add(ab.build());
+        // Create an Apply Action
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
+
+        // Wrap our Apply Action in an Instruction
+        InstructionBuilder ib = new InstructionBuilder();
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+        ib.setOrder(0);
+        ib.setKey(new InstructionKey(0));
+
+        // Put our Instruction in a list of Instructions
+        InstructionsBuilder isb = new InstructionsBuilder();
+        List<Instruction> instructions = new ArrayList<Instruction>();
+        instructions.add(ib.build());
+        isb.setInstruction(instructions);
+        return isb;
     }
 
     @Override
     public void initializeOFFlowRules(Node openflowNode) {
     }
+
+    private NodeBuilder createNodeBuilder(String nodeId) {
+        NodeBuilder builder = new NodeBuilder();
+        builder.setId(new NodeId(nodeId));
+        builder.setKey(new NodeKey(builder.getId()));
+        return builder;
+    }
+
+    private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder node) {
+        return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, node.getKey()).toInstance();
+    }
 }
index cfa38637761a95e959c1f712405354859c1ee70d..3dba186b622b1101db59a2814aade07c8db3fa97 100644 (file)
@@ -29,6 +29,7 @@ public class Bridge extends Table<Bridge> {
     private OvsDBSet<String> fail_mode;
     private OvsDBSet<UUID> sflow;
     private OvsDBSet<UUID> netflow;
+    private OvsDBSet<String> protocols;
     private OvsDBMap<String, String> status;
     private Boolean stp_enable;
     private OvsDBMap<String, String> other_config;
@@ -128,6 +129,14 @@ public class Bridge extends Table<Bridge> {
         return stp_enable;
     }
 
+    public OvsDBSet<String> getProtocols() {
+        return protocols;
+    }
+
+    public void setProtocols(OvsDBSet<String> protocols) {
+        this.protocols = protocols;
+    }
+
     public void setStp_enable(Boolean stp_enable) {
         this.stp_enable = stp_enable;
     }