Add create subnet operation
diff --git a/openstack/networking/v2/subnets/requests.go b/openstack/networking/v2/subnets/requests.go
index 9d23e56..93641d9 100644
--- a/openstack/networking/v2/subnets/requests.go
+++ b/openstack/networking/v2/subnets/requests.go
@@ -68,3 +68,94 @@
 	}
 	return &s, nil
 }
+
+const (
+	IPv4 = 4
+	IPv6 = 6
+)
+
+type SubnetOpts struct {
+	// Required
+	NetworkID string
+	CIDR      string
+	// Optional
+	Name            string
+	TenantID        string
+	AllocationPools []AllocationPool
+	GatewayIP       string
+	IPVersion       int
+	ID              string
+	EnableDHCP      *bool
+}
+
+// maybeString returns nil for empty strings and nil for empty.
+func maybeString(original string) *string {
+	if original != "" {
+		return &original
+	}
+	return nil
+}
+
+func Create(c *gophercloud.ServiceClient, opts SubnetOpts) (*Subnet, error) {
+	// Validate required options
+	if opts.NetworkID == "" {
+		return nil, ErrNetworkIDRequired
+	}
+	if opts.CIDR == "" {
+		return nil, ErrCIDRRequired
+	}
+	if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
+		return nil, ErrInvalidIPType
+	}
+
+	type subnet struct {
+		NetworkID       string           `json:"network_id"`
+		CIDR            string           `json:"cidr"`
+		Name            *string          `json:"name,omitempty"`
+		TenantID        *string          `json:"tenant_id,omitempty"`
+		AllocationPools []AllocationPool `json:"allocation_pools,omitempty"`
+		GatewayIP       *string          `json:"gateway_ip,omitempty"`
+		IPVersion       int              `json:"ip_version,omitempty"`
+		ID              *string          `json:"id,omitempty"`
+		EnableDHCP      *bool            `json:"enable_dhcp,omitempty"`
+	}
+	type request struct {
+		Subnet subnet `json:"subnet"`
+	}
+
+	reqBody := request{Subnet: subnet{
+		NetworkID: opts.NetworkID,
+		CIDR:      opts.CIDR,
+	}}
+
+	reqBody.Subnet.Name = maybeString(opts.Name)
+	reqBody.Subnet.TenantID = maybeString(opts.TenantID)
+	reqBody.Subnet.GatewayIP = maybeString(opts.GatewayIP)
+	reqBody.Subnet.ID = maybeString(opts.ID)
+	reqBody.Subnet.EnableDHCP = opts.EnableDHCP
+
+	if opts.IPVersion != 0 {
+		reqBody.Subnet.IPVersion = opts.IPVersion
+	}
+
+	if len(opts.AllocationPools) != 0 {
+		reqBody.Subnet.AllocationPools = opts.AllocationPools
+	}
+
+	type response struct {
+		Subnet *Subnet `json:"subnet"`
+	}
+
+	var res response
+	_, err := perigee.Request("POST", CreateURL(c), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		ReqBody:     &reqBody,
+		Results:     &res,
+		OkCodes:     []int{201},
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return res.Subnet, nil
+}