diff --git a/lib/opcodes.py b/lib/opcodes.py
index 5a331f140d55e814ccf48589493c1e6762e89975..b1ef8d659949aa61292a30692ec8a7d5f7fae42b 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -81,6 +81,9 @@ _PTags = ("tags", ht.NoDefault, ht.TListOf(ht.TNonEmptyString))
 #: Ignore consistency
 _PIgnoreConsistency = ("ignore_consistency", False, ht.TBool)
 
+#: a required network name
+_PNetworkName = ("network_name", ht.NoDefault, ht.TNonEmptyString)
+
 #: OP_ID conversion regular expression
 _OPID_RE = re.compile("([a-z])([A-Z])")
 
@@ -1286,6 +1289,26 @@ class OpTestDummy(OpCode):
   WITH_LU = False
 
 
+# Network opcodes
+class OpNetworkAdd(OpCode):
+  """Add an IP network to the cluster."""
+  OP_DSC_FIELD = "network_name"
+  OP_PARAMS = [
+    _PNetworkName,
+    ("network", None, ht.TString),
+    ("gateway", None, ht.TMaybeString),
+    ("reserved_ips", None, ht.TOr(ht.TListOf(ht.TNonEmptyString), ht.TNone)),
+    ]
+
+
+class OpNetworkQuery(OpCode):
+  """Compute the list of networks."""
+  OP_PARAMS = [
+    _POutputFields,
+    ("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString)),
+    ]
+
+
 def _GetOpList():
   """Returns list of all defined opcodes.